Xóa nhiều bản ghi bằng REST


97

Cách REST-ful để xóa nhiều mục là gì?

Trường hợp sử dụng của tôi là tôi có Bộ sưu tập xương sống trong đó tôi cần có thể xóa nhiều mục cùng một lúc. Các tùy chọn dường như là:

  1. Gửi yêu cầu XÓA cho mọi bản ghi (có vẻ như là một ý tưởng tồi nếu có khả năng có hàng tá mục);
  2. Gửi một XÓA trong đó ID cần xóa được xâu chuỗi lại với nhau trong URL (tức là, "/ records / 1; 2; 3");
  3. Theo cách không REST, hãy gửi một đối tượng JSON tùy chỉnh có chứa ID được đánh dấu để xóa.

Tất cả các tùy chọn đều ít hơn lý tưởng.

Đây có vẻ như là một vùng xám của quy ước REST.


Câu trả lời:


92
  1. Là một lựa chọn RESTful khả thi, nhưng rõ ràng là có những hạn chế mà bạn đã mô tả.
  2. Đừng làm điều này. Nó sẽ được người trung gian hiểu là "XÓA tài nguyên (đơn) tại /records/1;2;3" - Vì vậy, phản hồi 2xx cho điều này có thể khiến họ xóa bộ nhớ cache của họ /records/1;2;3; không thanh trừng /records/1, /records/2hoặc /records/3; ủy quyền một phản hồi 410 cho /records/1;2;3hoặc những thứ khác không có ý nghĩa theo quan điểm của bạn.
  3. Lựa chọn này là tốt nhất và có thể được thực hiện REST một cách chính xác. Nếu bạn đang tạo một API và bạn muốn cho phép thay đổi hàng loạt tài nguyên, bạn có thể sử dụng REST để làm điều đó, nhưng chính xác như thế nào thì không nhiều người rõ ràng ngay lập tức. Một phương pháp là tạo tài nguyên 'yêu cầu thay đổi' (ví dụ: bằng cách ĐĂNG một nội dung chẳng hạn như records=[1,2,3]đến /delete-requests) và thăm dò tài nguyên đã tạo (được chỉ định bởi Locationtiêu đề của phản hồi) để tìm hiểu xem yêu cầu của bạn đã được chấp nhận chưa, bị từ chối, đang được thực hiện hoặc đã hoàn thành. Điều này rất hữu ích cho các hoạt động kéo dài. Một cách khác là gửi một PATCHyêu cầu đến tài nguyên danh sách ,/records, phần nội dung chứa danh sách các tài nguyên và hành động cần thực hiện trên các tài nguyên đó (ở bất kỳ định dạng nào bạn muốn hỗ trợ). Điều này hữu ích cho các hoạt động nhanh chóng trong đó mã phản hồi cho yêu cầu có thể cho biết kết quả của hoạt động.

Mọi thứ đều có thể đạt được trong khi vẫn nằm trong các ràng buộc của REST, và thường thì câu trả lời là biến "vấn đề" thành một tài nguyên và cung cấp cho nó một URL.
Vì vậy, tất cả các hoạt động hàng loạt, chẳng hạn như xóa ở đây hoặc ĐĂNG nhiều mục vào một danh sách hoặc thực hiện cùng một chỉnh sửa đối với một nhóm tài nguyên, đều có thể được xử lý bằng cách tạo danh sách "hoạt động hàng loạt" và ĐĂNG hoạt động mới của bạn lên đó.

Đừng quên, REST không phải là cách duy nhất để giải quyết mọi vấn đề. “REST” chỉ là một phong cách kiến ​​trúc và bạn không cần phải tuân theo nó (nhưng bạn sẽ mất đi những lợi ích nhất định của Internet nếu không). Tôi khuyên bạn nên xem danh sách các kiến trúc API HTTP này và chọn một kiến trúc phù hợp với bạn. Chỉ cần tự nhận thức về những gì bạn mất đi nếu bạn chọn một kiến ​​trúc khác và đưa ra quyết định sáng suốt dựa trên trường hợp sử dụng của bạn.

Có một số câu trả lời không tốt cho câu hỏi này trên Mẫu xử lý các hoạt động hàng loạt trong dịch vụ web REST? có quá nhiều phiếu tán thành, nhưng cũng nên đọc.


2
Bạn không phải lo lắng về máy chủ của mình, mà là trung gian, CDN, proxy bộ nhớ đệm, v.v. Internet là một hệ thống nhiều lớp. Đó là lý do nó hoạt động rất tốt. Roy xác định khía cạnh nào của hệ thống là cần thiết cho sự thành công của nó và đặt tên chúng là REST. Nếu bạn đưa ra DELETEyêu cầu, bất cứ điều gì nằm giữa người được yêu cầu và máy chủ sẽ cho rằng một tài nguyên duy nhất, tại URL được chỉ định, đang bị xóa. Các chuỗi truy vấn là các phần không rõ ràng của URL đến các thiết bị này, vì vậy, không quan trọng bạn chỉ định API của mình như thế nào, chúng không được bảo mật về kiến ​​thức này nên không thể hoạt động khác.
Nicholas Shanks

3
/ hồ sơ / 1; 2; 3 sẽ không làm việc nếu bạn có một nguồn lực rất nhiều để xóa do hạn chế chiều dài URI
dukethrash

3
Lưu ý rằng nếu xem xét DELETE và cơ quan xác định tài nguyên để thanh lọc, thì một số bên trung gian có thể không chuyển tiếp nội dung đó. Ngoài ra, một số máy khách HTTP không thể thêm phần thân vào một DELETE. Xem stackoverflow.com/questions/299628/…
Luke Puplett,

3
@LukePuplett Tôi chỉ đơn giản nói rằng việc chuyển một cơ quan yêu cầu với một DELETEyêu cầu bị cấm. Đừng làm vậy. Nếu bạn làm vậy, tôi sẽ ăn thịt con bạn. Nom Nom Nom.
Nicholas Shanks,

3
Vấn đề với đối số # 3 là nó có cùng hình phạt với đối số phản đối số 2. Việc tạo để xóa tài nguyên không phải là thứ mà các proxy ngược dòng sẽ biết cách xử lý - đối số truy cập tương tự được nêu ra chống lại phương pháp # 2.
LB2

16

Nếu GET /records?filteringCriteriatrả về mảng tất cả các bản ghi phù hợp với tiêu chí, thì DELETE /records?filteringCriteriacó thể xóa tất cả các bản ghi đó.

Trong trường hợp này, câu trả lời cho câu hỏi của bạn sẽ là DELETE /records?id=1&id=2&id=3.


1
Tôi cũng đi đến kết luận này: chỉ cần chuyển động từ sang những gì bạn muốn làm. Tôi không hiểu làm thế nào những gì xảy ra với GET không đi với XÓA.
Luke Puplett

9
GET /records?id=1&id=2&id=3không không có nghĩa là “có được ba hồ sơ với ID 1, 2 & 3”, nó có nghĩa là “có được nguồn tài nguyên duy nhất với URL path / hồ sơ? id = 1 & id = 2 & id = 3” mà có thể là một hình ảnh của một củ cải, một văn bản đơn giản tài liệu chứa số "42" bằng tiếng Trung, hoặc có thể không tồn tại.
Nicholas Shanks

Hãy xem xét những điều sau: hai yêu cầu tuần tự cho /records?id=1/records?id=2được gửi, và phản hồi của chúng được lưu vào bộ nhớ cache bởi một số bên trung gian (ví dụ: trình duyệt hoặc ISP của bạn). Nếu internet biết ứng dụng của bạn có nghĩa là gì, thì đó là lý do mà một yêu cầu /records?id=1&id=2có thể được bộ nhớ cache trả lại đơn giản bằng cách hợp nhất (bằng cách nào đó) hai kết quả mà nó đã có mà không cần phải hỏi máy chủ gốc. Nhưng điều này là không thể. /records?id=1&id=2có thể không hợp lệ (chỉ cho phép 1 ID cho mỗi yêu cầu) hoặc có thể trả về thứ gì đó hoàn toàn khác (củ cải).
Nicholas Shanks

Đây là một vấn đề cơ bản về bộ nhớ đệm tài nguyên. Nếu DBA của tôi trực tiếp làm thay đổi trạng thái, thì bộ nhớ đệm hiện không đồng bộ. Bạn đưa ra ví dụ 410 do người trung gian trả về, nhưng 410 là để xóa vĩnh viễn, khi XÓA, bộ nhớ cache có thể xóa vị trí của nó cho URL đó, nhưng nó sẽ không gửi 410 hoặc 404, vì nó không biết liệu DBA không chỉ đặt tài nguyên ngay lập tức trở lại nguồn gốc.
Luke Puplett,

4
@NicholasCảm ơn tôi thực sự không đồng ý. Nếu kết quả được lưu vào bộ nhớ đệm, đó là lỗi của máy chủ. Và nếu bạn đang nói về thiết kế của API, hy vọng bạn là người viết mã cho máy chủ. Cho dù bạn sử dụng id[]=1&id[]=2hay id=1&id=2trong chuỗi truy vấn để đại diện cho một mảng giá trị, thì chuỗi truy vấn đó chỉ đại diện cho điều đó. Và tôi nghĩ rằng việc để chuỗi truy vấn đại diện cho một bộ lọc là điều cực kỳ phổ biến và hay. Bên cạnh đó, nếu bạn cho phép xóa và cập nhật, đừng lưu vào bộ nhớ cache các GETyêu cầu. Nếu bạn làm vậy, khách hàng sẽ giữ trạng thái cũ.
Joseph Nields

8

Tôi nghĩ rằng Mozilla Storage Service SyncStorage API v1.5 là một cách tốt để xóa nhiều bản ghi bằng REST.

Xóa toàn bộ bộ sưu tập.

DELETE https://<endpoint-url>/storage/<collection>

Xóa nhiều BSO khỏi một bộ sưu tập với một yêu cầu duy nhất.

DELETE https://<endpoint-url>/storage/<collection>?ids=<ids>

id : xóa BSO khỏi tập hợp có id nằm trong danh sách được phân tách bằng dấu phẩy đã cung cấp. Có thể cung cấp tối đa 100 id.

Xóa BSO tại vị trí đã cho.

DELETE https://<endpoint-url>/storage/<collection>/<id>

http://moz-services-docs.readthedocs.io/en/latest/storage/apis-1.5.html#api-instructions


Đây có vẻ như là một giải pháp tốt. Tôi đoán nếu mozilla nghĩ rằng nó là chính xác thì nó phải là? Câu hỏi duy nhất sau đó là xử lý lỗi. Giả sử họ chuyển? Ids = 1,2,3 và id 3 không tồn tại, bạn xóa 1 và 2 sau đó trả lời bằng 200 vì người yêu cầu muốn 3 biến mất và nó không có ở đó nên không quan trọng? hoặc điều gì sẽ xảy ra nếu họ được phép xóa 1 chứ không phải 2 ... bạn không xóa gì và phản hồi với lỗi hay bạn xóa những gì bạn có thể và để lại những thứ khác ...
tempcke 19/1018

Tôi thường sẽ trả về một phản hồi thành công vì trạng thái kết thúc là như nhau bất kể. Điều này cũng đơn giản hóa logic trên máy khách vì họ không còn phải xử lý trạng thái lỗi đó nữa. Đối với trường hợp ủy quyền, tôi sẽ không yêu cầu toàn bộ ... nhưng thực sự nó phụ thuộc vào trường hợp sử dụng của bạn.
Nathan Phetteplace

3

Đây có vẻ như là một vùng xám của quy ước REST.

Có, cho đến nay tôi mới chỉ xem qua một hướng dẫn thiết kế API REST đề cập đến các hoạt động hàng loạt (chẳng hạn như xóa hàng loạt): hướng dẫn thiết kế google api .

Hướng dẫn này đề cập đến việc tạo các phương thức "tùy chỉnh" có thể được liên kết thông qua một tài nguyên bằng cách sử dụng dấu hai chấm, ví dụ: https://service.name/v1/some/resource/name:customVerbnó cũng đề cập rõ ràng các hoạt động hàng loạt như trường hợp sử dụng:

Một phương thức tùy chỉnh có thể được liên kết với một tài nguyên, một bộ sưu tập hoặc một dịch vụ. Nó có thể nhận một yêu cầu tùy ý và trả lại một phản hồi tùy ý, đồng thời cũng hỗ trợ yêu cầu và phản hồi trực tuyến. [...] Các phương thức tùy chỉnh nên sử dụng động từ HTTP POST vì nó có ngữ nghĩa linh hoạt nhất [...] Đối với các phương thức quan trọng về hiệu suất, có thể hữu ích khi cung cấp các phương thức hàng loạt tùy chỉnh để giảm chi phí cho mỗi yêu cầu .

Vì vậy, bạn có thể làm như sau theo hướng dẫn api của google:

POST /api/path/to/your/collection:batchDelete

... để xóa một loạt các mục trong tài nguyên bộ sưu tập của bạn.


Có phải giải pháp khả thi là danh sách các mục được giao tiếp thông qua một mảng được định dạng JSON không?
Daniele

vâng, chắc chắn. bạn có thể ĐĂNG một trọng tải trong đó id được gửi qua mảng json.
B12Toaster

Điều thú vị là hướng dẫn API của Google đã nói If the HTTP verb used for the custom method does not accept an HTTP request body (GET, DELETE), the HTTP configuration of such method must not use the body clause at all,ở chương Phương pháp tùy chỉnh. Nhưng GET accounts.locations.batchGetapi là phương thức GET với body. Thật là kỳ lạ. developers.google.com/my-business/reference/rest/v4/...
鄭元傑

@ 鄭元傑 đồng ý, có vẻ hơi kỳ lạ ngay từ cái nhìn đầu tiên nhưng nếu bạn nhìn kỹ thì đó thực sự là một POSTphương thức http được sử dụng và chỉ có phương thức tùy chỉnh được đặt tên batchGet. Tôi đoán google làm điều đó để (a) tuân theo quy tắc của họ rằng tất cả các phương pháp tùy chỉnh cần phải là POST(xem câu trả lời của tôi) và (b) để giúp mọi người dễ dàng đặt "bộ lọc" vào nội dung để bạn không phải thoát hoặc mã hóa bộ lọc như với chuỗi truy vấn. Mặt khác, tất nhiên, là điều này là không thực sự khả năng lưu nhớ nữa ...
B12Toaster

https://service.name/v1/some/resource/name:customVerbkhông phải là RESTful theo định nghĩa.
ngừng hoạt động

2

Tôi đã cho phép thay thế bán buôn một bộ sưu tập, ví dụ như PUT ~/people/123/shoestrong đó phần thân là toàn bộ đại diện bộ sưu tập.

Điều này hoạt động đối với các bộ sưu tập nhỏ của các mục trong đó khách hàng muốn xem lại các mục và cắt bỏ một số và thêm một số mục khác vào rồi cập nhật máy chủ. Họ có thể PUT một tập hợp trống để xóa tất cả.

Điều này có nghĩa là GET ~/people/123/shoes/9sẽ vẫn còn trong bộ nhớ cache mặc dù PUT đã xóa nó, nhưng đó chỉ là vấn đề bộ nhớ đệm và sẽ là vấn đề nếu một số người khác xóa giày.

Các API dữ liệu / hệ thống của tôi luôn sử dụng ETags thay vì thời gian hết hạn, do đó máy chủ bị truy cập theo từng yêu cầu và tôi yêu cầu tiêu đề phiên bản / đồng thời chính xác để thay đổi dữ liệu. Đối với các API được căn chỉnh ở chế độ chỉ đọc và chế độ xem / báo cáo, tôi sử dụng thời gian hết hạn để giảm số lần truy cập vào nguồn gốc, ví dụ: bảng xếp hạng có thể tốt trong 10 phút.

Đối với các bộ sưu tập lớn hơn nhiều, chẳng hạn như ~/people, tôi có xu hướng không cần xóa nhiều lần, trường hợp sử dụng có xu hướng không tự nhiên phát sinh và vì vậy XÓA duy nhất hoạt động tốt.

Trong tương lai, và từ kinh nghiệm xây dựng các API REST và giải quyết các vấn đề và yêu cầu tương tự, như kiểm toán, tôi có xu hướng chỉ sử dụng các động từ GET và POST và thiết kế xung quanh các sự kiện, ví dụ: ĐĂNG một sự kiện thay đổi địa chỉ, mặc dù tôi nghi ngờ rằng sẽ đi kèm với một loạt vấn đề của riêng nó :)

Tôi cũng sẽ cho phép các nhà phát triển front-end xây dựng các API của riêng họ sử dụng các API back-end chặt chẽ hơn vì thường có những lý do thực tế, hợp lệ từ phía khách hàng khiến họ không thích các thiết kế API REST "Fielding zealot" nghiêm ngặt và vì năng suất và lý do phân lớp bộ nhớ cache.


Tôi yêu thích câu trả lời này cho đến khi tôi đọc câu cuối cùng :) Tôi chưa bao giờ thấy một trường hợp sử dụng nào mà việc áp dụng REST nghiêm ngặt lại có tác dụng bất lợi. Chắc chắn nó có thể tạo ra nhiều mã hơn để viết ở cả hai đầu, nhưng bạn sẽ có một hệ thống an toàn hơn, sạch hơn, ít ghép nối hơn.
Nicholas Shanks

Haha. Nó thực sự trở thành một khuôn mẫu! Phần hỗ trợ cho giao diện người dùng, nó được gọi trên radar công nghệ ThoughtWorks. Nó cũng cho phép viết nhiều logic ứng dụng hơn, có thể nói là rườm rà, JavaScript, và rõ ràng là có thể cập nhật mà không cần ứng dụng khách, vì vậy, hãy cập nhật cho ứng dụng iOS.
Luke Puplett,

Đọc lướt bốn lượt truy cập đầu tiên từ Google, có vẻ như kỹ thuật BFF này chỉ có thể hoạt động khi khách hàng nằm trong tầm kiểm soát của bạn . Các nhà phát triển khách hàng phát triển API mà họ muốn, ánh xạ các cuộc gọi tới các API microservice là back end thực sự. Trong sơ đồ này: samnewman.io/patterns/architectural/bff/#bff Tôi sẽ đặt dòng "Chu vi" bên dưới các hộp BFF - mỗi hộp chỉ đơn giản là một phần của máy khách. Nó thậm chí có thể sống bên ngoài trung tâm dữ liệu chứa các microservices. Tôi cũng không thấy cách REST không áp dụng cho cả hai giao diện (máy khách / BFF và BFF / microservice).
Nicholas Shanks

1
Vâng, đó là một điểm tốt. Ví dụ: nó thường xảy ra khi bạn có một nhóm xây dựng vi dịch vụ và một nhóm tạo ra một ứng dụng góc cạnh và nhóm nhà phát triển đó là những người thuộc loại front-end hơn, những người không thích phải làm việc với một loạt các dịch vụ thuần túy nhất. Mặc dù tôi không thấy lý do gì khiến bạn không thể sử dụng cùng một mẫu để trừu tượng hóa các microservices và tổng hợp thành một mặt tiền dễ sử dụng hơn cho khách hàng của bạn, sao cho các microservices có thể được thay đổi mà không ảnh hưởng đến mặt tiền.
Luke Puplett,

Điểm cuối API phải mô hình hóa nhu cầu của miền và doanh nghiệp. Mã để giải quyết những vấn đề đó và tránh kỹ thuật quá mức để tuân thủ các thông số kỹ thuật nghiêm ngặt và không linh hoạt trong nhiều thời gian. REST dù sao cũng không phải là hướng dẫn.
Victorio Berra
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.