Design REST-completo: abordagem recomendada para buscar entidades relacionadas

5

Suponha que eu tenha duas entidades author e post , onde cada post tem um autor . Implementadas são essas chamadas REST

  1. Obtenha uma lista paginada de postagens : GET /posts?page={page}

  2. Obtenha uma lista de autores: GET /authors

  3. Obtenha um único autor: GET /authors/{id}

Suponha que eu também tenha um cliente usando o serviço REST. Este cliente quer mostrar uma lista paginada de postagens com autores relacionados.

Agora, como o serviço REST funcionaria em relação às entidades relacionadas? Existem os seguintes métodos:

  1. Deixe a chamada GET /posts?page=1 retornar as postagens e os autores relacionados em uma única chamada. Opcionalmente, torne isso um parâmetro separado, por exemplo, GET /posts?page=1&related=true ou GET /posts/related?page=1 .

  2. Deixe o cliente percorrer as postagens e obter o autor de cada postagem usando a GET /author/{id} chamada.

  3. Deixe a chamada REST para os autores aceitarem uma lista de ID's como um filtro, para que o cliente possa obter os autores relacionados em uma chamada, por exemplo. GET /authors?ids=10,12,16,30,43,44,58 .

O método 1 é o mais fácil da perspectiva do cliente, pois obtém todos os dados necessários em uma chamada. Mas o serviço REST é limitado aqui, não deve precisar se ajustar a nenhum cliente em particular porque cada cliente tem outros requisitos.

O método 2 é a abordagem REST mais limpa, mas digamos que uma página tenha 30 postagens, o cliente precisa fazer 30 chamadas REST adicionais para recuperar os autores relacionados. Isso é muito ineficiente.

O método 3 é talvez o melhor dos três, já que é uma implementação relativamente limpa do REST (em comparação com o método 1) e requer apenas uma chamada extra por página.

Existe uma abordagem recomendada aqui?

    
por Jaap van Hengstum 17.12.2014 / 16:18
fonte

4 respostas

3

Isso é o que links são para:

Por exemplo solicitando o primeiro post via GET http://example.com/posts/1

{
    "id": "1",
    "author": {
        "nickname": "me"
    },
    "links": [
        {
            "rel": "self",
            "href": "http://example.com/posts/1"
        },
        {
            "rel": "author",
            "href": "http://example.com/authors/me"
        }
    ]
}

A resposta contém um link para o autor (chamado me ). Se você quiser recuperar todas as mensagens de mim , você faria um GET para http://example.com/posts?author=me ; e se você quiser paginado, você adicionaria um parâmetro de consulta como http://example.com/posts?author=me&page=1 .

Digamos que você tenha colaborações entre vários autores. A resposta inicial seria:

{
    "id": "1",
    "authors": [
        {
            "nickname": "me"
        },
        {
            "nickname": "mo"
        },
        {
            "nickname": "ma"
        }
    ],
    "links": [
        {
            "rel": "self",
            "href": "http://example.com/posts/1"
        },
        {
            "rel": "author",
            "href": "http://example.com/authors/me"
        },
        {
            "rel": "author",
            "href": "http://example.com/authors/mo"
        },
        {
            "rel": "author",
            "href": "http://example.com/authors/ma"
        }
    ]
}

Por outro lado, sob a seção links do autor, deve haver apenas uma referência à última postagem (para evitar muitos dados lá).

Se você deseja obter um conjunto de todas as postagens colaborativas do trio acima, faça a seguinte consulta:

GET http://example.com/posts?author=mo,me,ma

Se você quiser todas as postagens - incluindo a colaborativa - do trio, faça uma consulta como esta:

GET http://example.com/posts?author=mo|me|ma

Esta é uma abordagem clara e direta.

Para expressar que algo está relacionado , use links . Se você quiser filtrar, faça isso por querystring.

    
por 17.12.2014 / 22:42
fonte
2

Você pode fazer algo semelhante ao que os discogs fazem na API, link . Ao solicitar um release / releases / {release_id}, a resposta também inclui um subconjunto de dados do artista, extraído do corpo da resposta:

{    
    "title": "Never Gonna Give You Up",
    "id": 249504,
    "artists": [
        {
            "anv": "",
            "id": 72872,
            "join": "",
            "name": "Rick Astley",
            "resource_url": "https://api.discogs.com/artists/72872",
            "role": "",
            "tracks": ""
        }
    ]
}

No seu caso, em vez de artistas, ele poderia ser o autor e, se o cliente quiser mais informações sobre o autor, ele deve usar GET / authors / {id}.

    
por 17.12.2014 / 16:53
fonte
0

Você também pode fazer isso em uma chamada incorporando autores dentro de postagens . A Linguagem de aplicativos de hipertexto JSON descreve como fazer isso, consulte o link

por exemplo. (cópia modificada do documento):

{
    "_links": {
        "self": { "href": "/posts" },
        "next": { "href": "/posts?page=2" },
        "find": { "href": "/posts{?id}", "templated": true }
    },
    "_embedded": {
        "post": [{
            "_links": {
                "self": { "href": "/posts/321" },
                "author": { "href": "/author/alan-watts" }
            },
            "_embedded": {
                "author": {
                    "_links": { "self": { "href": "/author/alan-watts" } },
                    "name": "Alan Watts",
                    "born": "January 6, 1915",
                    "died": "November 16, 1973"
                }
            }
            "title": "foo"
        }, {
            "_links": {
                "self": { "href": "/posts/123" },
                "author": { "href": "/author/alan-watts" }
            },
            "_embedded": {
                "author": {
                    "_links": { "self": { "href": "/author/alan-watts" } },
                    "name": "Alan Watts",
                    "born": "January 6, 1915",
                    "died": "November 16, 1973"
                }
            },
            "title": "bar"
        }]
    }
}
    
por 18.12.2014 / 02:49
fonte
0

Você pode se inspirar no protocolo ODATA como uma variação da sua opção 1. Ele tem as chamadas opções de consulta, uma das quais é $ expand, que leva o valor do recurso relacionado a retornar.

A opção de consulta do sistema $ expand especifica os recursos relacionados a serem incluídos de acordo com os recursos recuperados. A solicitação abaixo retorna pessoas com a propriedade de navegação Posts de um autor.

GET / authors / {id} / $ expand = Posts

link

Você pode criar o seu próprio chamado $ related.

    
por 18.12.2014 / 06:04
fonte