developer tip

REST API-단일 요청으로 대량 생성 또는 업데이트

optionbox 2020. 10. 17. 10:24
반응형

REST API-단일 요청으로 대량 생성 또는 업데이트


의이 두 자원은 가정하자 BinderDoc것을 연결 관계의 의미를 Doc하고 Binder자신에 서있다. Doc수도 있고 있지 않을 가능성에 속한다 BinderBinder비어있을 수 있습니다.

사용자가 Docs 컬렉션을 보낼 수있는 REST API를 디자인 하려면 다음과 같이 IN A SINGLE REQUEST .

{
  "docs": [
    {"doc_number": 1, "binder": 1}, 
    {"doc_number": 5, "binder": 8},
    {"doc_number": 6, "binder": 3}
  ]
}

그리고 각 문서에 대한 docs,

  • (가) 경우 doc다음 존재에 할당Binder
  • doc존재하지 않는 경우 생성 한 다음 할당합니다.

이것이 어떻게 구현되어야하는지에 대해 정말 혼란 스럽습니다.

  • 사용할 HTTP 방법은 무엇입니까?
  • 어떤 응답 코드를 반환해야합니까?
  • REST에도 적합합니까?
  • URI는 어떻게 생겼습니까? /binders/docs?
  • 대량 요청을 처리 할 때 일부 항목에서 오류가 발생하지만 다른 항목은 처리됩니다. 어떤 응답 코드를 반환해야합니까? 대량 작업은 원자 적이어야합니까?

나는 그들이 일반적으로 이것을 위해 디자인하기 때문에 이것을 처리하기 위해 POST 또는 PATCH 방법을 사용할 수 있다고 생각합니다.

  • POST메소드 사용 은 일반적으로 목록 리소스에서 사용될 때 요소를 추가하는 데 사용되지만이 메소드에 대해 여러 작업을 지원할 수도 있습니다. 이 답변 : How to Update a REST Resource Collection을 참조하십시오 . 입력에 대해 다른 표현 형식을 지원할 수도 있습니다 (배열 또는 단일 요소에 해당하는 경우).

    이 경우 업데이트를 설명하기 위해 형식을 정의 할 필요가 없습니다.

  • PATCH해당 요청이 부분 업데이트에 해당하므로 메서드를 사용하는 것도 적합합니다. RFC5789 ( http://tools.ietf.org/html/rfc5789 ) 에 따르면 :

    HTTP (Hypertext Transfer Protocol)를 확장하는 여러 응용 프로그램에는 부분적인 리소스 수정을 수행하는 기능이 필요합니다. 기존 HTTP PUT 방법은 문서의 완전한 대체 만 허용합니다. 이 제안은 기존 HTTP 리소스를 수정하기 위해 새로운 HTTP 메소드 인 PATCH를 추가합니다.

    이 경우 부분 업데이트를 설명하는 형식을 정의해야합니다.

나는이 경우에 그 생각, POST그리고 PATCH당신이 정말로 각 요소에 대해 수행 할 작업을 설명 할 필요가 없기 때문에 매우 유사하다. 보낼 표현의 형식에 따라 달라집니다.

의 경우 PUT는 좀 덜 명확합니다. 사실, 메소드를 사용할 때 PUT전체 목록을 제공해야합니다. 사실, 요청에 제공된 표현은 목록 리소스 1을 대체합니다.

리소스 경로와 관련하여 두 가지 옵션이 있습니다.

  • 문서 목록에 리소스 경로 사용

이 경우 요청에서 제공하는 표현에 바인더가있는 문서의 링크를 명시 적으로 제공해야합니다.

여기에 대한 샘플 경로가 /docs있습니다.

이러한 접근 방식의 내용은 다음과 POST같습니다.

[
    { "doc_number": 1, "binder": 4, (other fields in the case of creation) },
    { "doc_number": 2, "binder": 4, (other fields in the case of creation) },
    { "doc_number": 3, "binder": 5, (other fields in the case of creation) },
    (...)
]
  • 바인더 요소의 하위 리소스 경로 사용

또한 문서와 바인더 간의 링크를 설명하기 위해 하위 경로를 활용하는 것도 고려할 수 있습니다. 문서와 바인더 간의 연결에 관한 힌트는 이제 요청 콘텐츠 내에서 지정할 필요가 없습니다.

여기에 대한 샘플 경로가 /binder/{binderId}/docs있습니다. 이 경우 문서 목록을 메서드와 함께 보내 POST거나 PATCH문서 binderId가없는 경우 문서를 만든 후 식별자를 사용하여 바인더에 문서를 첨부 합니다.

이러한 접근 방식의 내용은 다음과 POST같습니다.

[
    { "doc_number": 1, (other fields in the case of creation) },
    { "doc_number": 2, (other fields in the case of creation) },
    { "doc_number": 3, (other fields in the case of creation) },
    (...)
]

응답과 관련하여 응답 수준과 반환 할 오류를 정의하는 것은 사용자에게 달려 있습니다. 상태 수준 (글로벌 수준)과 페이로드 수준 (얇은 수준)의 두 가지 수준이 있습니다. 또한 요청에 해당하는 모든 삽입 / 업데이트가 원자 적이어야하는지 여부를 정의하는 것은 사용자에게 달려 있습니다.

  • 원자

이 경우 HTTP 상태를 활용할 수 있습니다. 모든 것이 잘되면 상태가 200됩니다. 그렇지 않은 400경우 제공된 데이터가 올바르지 않거나 (예 : 바인더 ID가 유효하지 않음) 다른 상태와 같은 다른 상태 입니다.

  • 비 원자

이 경우 상태 200가 반환되고 수행 된 작업과 결국 오류가 발생하는 위치를 설명하는 것은 응답 표현에 달려 있습니다. ElasticSearch에는 대량 업데이트를 위해 REST API에 엔드 포인트가 있습니다. http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/bulk.html 수준에서 몇 가지 아이디어를 얻을 수 있습니다 .

  • 비동기

제공된 데이터를 처리하기 위해 비동기 처리를 구현할 수도 있습니다. 이 경우 HTTP 상태 반환은입니다 202. 클라이언트는 어떤 일이 발생하는지 확인하기 위해 추가 리소스를 가져와야합니다.

완료하기 전에 OData 사양이 내비게이션 링크 라는 기능을 사용하여 엔티티 간의 관계에 관한 문제를 해결하고 있음을 알고 싶습니다 . 아마도 당신은 이것을 볼 수 있습니다 ;-)

다음 링크도 도움이 될 수 있습니다 : https://templth.wordpress.com/2014/12/15/designing-a-web-api/ .

도움이 되었기를 바랍니다, Thierry


여러 리소스를 업데이트하고 생성하는 단일 요청이 멱 등성을 가질 가능성이 거의 없기 때문에 POST 또는 PATCH를 사용해야 할 것입니다.

하는 PATCH /docs것은 확실히 유효한 옵션입니다. 특정 시나리오에 대해 표준 패치 형식을 사용하는 것이 까다로울 수 있습니다. 이것에 대해 확실하지 않습니다.

200을 사용할 수 있습니다. 207-Multi Status를 사용할 수도 있습니다.

이것은 RESTful 방식으로 수행 할 수 있습니다. 제 생각에 핵심은 업데이트 / 작성할 문서 세트를 수용하도록 설계된 리소스를 확보하는 것입니다.

PATCH 방법을 사용하는 경우 작업이 원자 적이어야한다고 생각합니다. 즉, 207 상태 코드를 사용하지 않고 응답 본문에 성공과 실패를보고합니다. POST 작업을 사용하면 207 접근 방식이 실행 가능합니다. 성공한 작업과 실패한 작업을 전달하기 위해 자체 응답 본문을 디자인해야합니다. 나는 표준화 된 것을 모른다.


PUT ing

PUT /binders/{id}/docs 단일 문서를 작성 또는 업데이트하고 바인더에 연결

예 :

PUT /binders/1/docs HTTP/1.1
{
  "docNumber" : 1
}

패치 ING

PATCH /docs 문서가없는 경우 문서를 작성하고 바인더와 연결하십시오.

예 :

PATCH /docs HTTP/1.1
[
    { "op" : "add", "path" : "/binder/1/docs", "value" : { "doc_number" : 1 } },
    { "op" : "add", "path" : "/binder/8/docs", "value" : { "doc_number" : 8 } },
    { "op" : "add", "path" : "/binder/3/docs", "value" : { "doc_number" : 6 } }
] 

나중에 추가 인사이트를 포함 할 것이지만, 원하신다면 RFC 5789 , RFC 6902 및 William Durand의 Please를 살펴보십시오 . 바보 블로그 항목 처럼 패치하지 마십시오 .


내가 일한 프로젝트에서 우리는 '일괄'요청이라는 것을 구현하여이 문제를 해결했습니다. /batch다음 형식으로 json을 허용 하는 경로를 정의했습니다 .

[  
   {
      path: '/docs',
      method: 'post',
      body: {
         doc_number: 1,
         binder: 1
      }
   },
   {
      path: '/docs',
      method: 'post',
      body: {
         doc_number: 5,
         binder: 8
      }
   },
   {
      path: '/docs',
      method: 'post',
      body: {
         doc_number: 6,
         binder: 3
      }
   },
]

응답의 상태 코드는 207 (다중 상태)이며 다음과 같습니다.

[  
   {
      path: '/docs',
      method: 'post',
      body: {
         doc_number: 1,
         binder: 1
      }
      status: 200
   },
   {
      path: '/docs',
      method: 'post',
      body: {
         error: {
            msg: 'A document with doc_number 5 already exists'
            ...
         }
      },
      status: 409
   },
   {
      path: '/docs',
      method: 'post',
      body: {
         doc_number: 6,
         binder: 3
      },
      status: 200
   },
]

You could also add support for headers in this structure. We implemented something that proved useful which was variables to use between requests in a batch, meaning we can use the response from one request as input to another.

Facebook and Google have similar implementations:
https://developers.google.com/gmail/api/guides/batch
https://developers.facebook.com/docs/graph-api/making-multiple-requests

When you want to create or update a resource with the same call I would use either POST or PUT depending on the case. If the document already exist, do you want the entire document to be:

  1. Replaced by the document you send in (i.e. missing properties in request will be removed and already existing overwritten)?
  2. Merged with the document you send in (i.e. missing properties in request will not be removed and already existing properties will be overwritten)?

In case you want the behavior from alternative 1 you should use a POST and in case you want the behavior from alternative 2 you should use PUT.

http://restcookbook.com/HTTP%20Methods/put-vs-post/

As people already suggested you could also go for PATCH, but I prefer to keep API's simple and not use extra verbs if they are not needed.

참고URL : https://stackoverflow.com/questions/28596688/rest-api-bulk-create-or-update-in-single-request

반응형