REST kullanarak birden fazla kaydı silin


106

Birden çok öğeyi silmenin DİNLENME yolu nedir?

Benim kullanım durumum, aynı anda birden fazla öğeyi silebilmem gereken bir Omurga Koleksiyonum olması. Seçenekler şöyle görünüyor:

  1. Her kayıt için bir DELETE isteği gönderin (potansiyel olarak düzinelerce öğe varsa kötü bir fikir gibi görünür);
  2. Silinecek kimliklerin URL'de birbirine dizildiği bir DELETE gönderin (yani, "/ kayıtlar / 1; 2; 3");
  3. REST olmayan bir şekilde, silinmek üzere işaretlenmiş kimlikleri içeren özel bir JSON nesnesi gönderin.

Tüm seçenekler idealin altında.

Bu, REST sözleşmesinin gri bir alanı gibi görünüyor.


Yanıtlar:


95
  1. Uygulanabilir bir RESTful seçimdir, ancak açıkçası sizin tanımladığınız sınırlamalara sahiptir.
  2. Bunu yapma. Aracılar tarafından "(tek) kaynağı SİL" anlamına geldiği şeklinde yorumlanacaktır /records/1;2;3- Bu nedenle, buna 2xx yanıtı önbelleklerini temizlemelerine neden olabilir /records/1;2;3; değil temizlemek /records/1, /records/2ya da /records/3; 410 yanıtını /records/1;2;3veya sizin bakış açınıza göre anlamlı olmayan diğer şeyleri vekil edin.
  3. Bu seçim en iyisidir ve DİNLENEN bir şekilde yapılabilir. Bir API oluşturuyorsanız ve kaynaklarda toplu değişikliklere izin vermek istiyorsanız, bunu yapmak için REST'i kullanabilirsiniz, ancak çoğu kişi için tam olarak nasıl olduğu hemen belli değildir. Bir yöntem olan bir 'değişiklik talebi' kaynak oluşturmak (örneğin gibi bir vücut yayınlayarak records=[1,2,3]için /delete-requests) (ile belirtilen oluşturulan bir kaynağı ve anket Locationisteğiniz reddedildi kabul sürüyor olup olmadığını öğrenmek için tepki başlığındaki) veya tamamlandı. Bu, uzun süreli işlemler için kullanışlıdır. Başka bir yol da liste kaynağına istek göndermektirPATCH ,/records, gövdesi bu kaynaklar üzerinde gerçekleştirilecek kaynakların ve eylemlerin bir listesini içerir (hangi formatta desteklemek isterseniz). Bu, istek için yanıt kodunun işlemin sonucunu gösterebileceği hızlı işlemler için kullanışlıdır.

Her şey, REST kısıtlamaları dahilinde gerçekleştirilebilir ve genellikle cevap, "sorunu" bir kaynağa dönüştürmek ve ona bir URL vermektir.
Bu nedenle, burada silme veya birden çok öğeyi bir listeye POST gönderme veya bir kaynak kümesinde aynı düzenlemeyi yapma gibi toplu işlemlerin tümü, bir "toplu işlemler" listesi oluşturarak ve yeni işleminizi ona POST yaparak gerçekleştirilebilir.

Unutmayın, REST herhangi bir sorunu çözmenin tek yolu değildir. “DİNLENME” sadece bir mimari tarzı olduğunu ve yok olması ona uymak (ama bunu yapmazsanız internet belirli faydalar kaybetmek). Bu HTTP API mimarileri listesine bakmanızı ve size uygun olanı seçmenizi öneririm . Sadece başka bir mimari seçerseniz neleri kaybedeceğinizin farkında olun ve kullanım durumunuza göre bilinçli bir karar verin.

REST web hizmetlerinde toplu işlemleri işleme kalıpları ile ilgili bu sorunun bazı kötü yanıtları var mı? çok fazla olumlu oy içeren, ancak okunması gereken.


2
Endişelenmeniz gereken şey sunucunuz değil, aracılar, CDN'ler, önbelleğe alma vekilleri vb. İnternet katmanlı bir sistemdir. Bu kadar iyi çalışmasının nedeni budur . Roy, sistemin başarısı için hangi yönlerinin gerekli olduğunu belirledi ve onlara REST adını verdi. Bir DELETEtalepte bulunursanız , talep eden ile sunucu arasında ne olursa olsun, belirtilen URL'deki tek bir kaynağın silindiğini düşünecektir. Sorgu dizeleri, bu cihazlara yönelik URL'nin opak kısımlarıdır, bu nedenle API'nizi nasıl belirttiğiniz önemli değildir, bunlar bu bilgiye özel değildir, bu nedenle farklı davranamazlar.
Nicholas Shanks

4
/ records / 1; 2; 3, URI uzunluk kısıtlamaları nedeniyle silinecek çok fazla kaynağınız varsa çalışmaz
dukethrash

3
SİL ve tasfiye edilecek kaynakları tanımlayan bir organ düşünüldüğünde, bazı aracıların kuruluşu başkasına iletemeyebileceğini unutmayın. Ayrıca, bazı HTTP istemcileri bir DELETE'e gövde ekleyemez. Stackoverflow.com/questions/299628/… sayfasına
Luke Puplett

4
@LukePuplett Basitçe, bir istek gövdesini bir istekle iletmenin yasak olduğunu belirtmek isterim DELETE. Yapma. Eğer yaparsan çocuklarını yerim. Nom nom nom.
Nicholas Shanks

3
# 3 için argümanla ilgili sorun, # 2'ye karşı karşı argümanla aynı cezayı taşımasıdır. Silinecek kaynak oluşturmak, yukarı akış proxy'lerinin nasıl ele alınacağını bileceği bir şey değildir - yaklaşıma karşı ortaya çıkan aynı karşı argüman.
LB2

16

Eğer GET /records?filteringCriteriatüm kayıtların döner dizisi kriterleri, daha sonra DELETE /records?filteringCriteriabütün bu kayıtları silebilir.

Bu durumda sorunuzun cevabı olacaktır DELETE /records?id=1&id=2&id=3.


1
Ayrıca şu sonuca vardım: sadece fiili yapmak istediğiniz şeye çevirin. GET için geçerli olanın SİLİNE gitmediğini anlamıyorum.
Luke Puplett

9
GET /records?id=1&id=2&id=3yok değil “kimlikleri 1, 2 ve 3 ile üç kaydı olsun” demek, bu bir şalgam bir resmi olabilir, bir düz metin “URL yolu / kayıtların? id = 1 & id = 2 & id = 3 ile tek kaynak olsun” demektir Çince "42" sayısını içeren belge mevcut olmayabilir.
Nicholas Shanks

Aşağıdakileri göz önünde bulundurun: iki sıralı istek gönderilir /records?id=1ve /records?id=2gönderilir ve yanıtları bazı aracılar tarafından önbelleğe alınır (örn. Tarayıcınız veya ISS). İnternet, uygulamanızın bununla ne anlama geldiğini biliyorsa, o zaman /records?id=1&id=2, başlangıç ​​sunucusuna sormaya gerek kalmadan zaten sahip olduğu iki sonucu birleştirerek (bir şekilde) önbellekten bir isteğin geri döndürülebileceğini düşünür. Ancak bu mümkün değil. /records?id=1&id=2geçersiz olabilir (istek başına yalnızca 1 kimliğe izin verilir) veya tamamen farklı bir şey (bir şalgam) iade edebilir.
Nicholas Shanks

Bu, temel bir kaynak önbelleğe alma sorunudur. DBA'm durumu doğrudan değiştirdiyse, önbellekler artık senkronize olmuyor. Aracı tarafından döndürülen bir 410 örneği veriyorsunuz, ancak 410 kalıcı kaldırma içindir, SİLDİĞİNDE bir önbellek bu URL için yuvasını temizleyebilir, ancak bir DBA olup olmadığını bilmediği için bir 410 veya 404 göndermez. kaynağı hemen başlangıç ​​noktasına geri koymakla kalmadı.
Luke Puplett

4
@NicholasShanks Gerçekten katılmıyorum. Sonuçlar önbelleğe alınmışsa, bu sunucunun hatasıdır. Ve API'nin tasarımından bahsediyorsanız, umarız sunucu için kod yazan sizsinizdir. Bir değer dizisini temsil etmek için sorgu dizesinde id[]=1&id[]=2veya kullansanız da id=1&id=2, bu sorgu dizesi tam olarak bunu temsil eder. Sorgu dizesinin bir filtreyi temsil etmesinin son derece yaygın ve iyi bir uygulama olduğunu düşünüyorum. Ayrıca, silme ve güncellemelere izin verirseniz, GETistekleri önbelleğe almayın. Bunu yaparsanız, müşteriler bayat halini koruyacaktır.
Joseph Nields

12

Mozilla Storage Service SyncStorage API v1.5'in REST kullanarak birden fazla kaydı silmenin iyi bir yolu olduğunu düşünüyorum.

Tüm koleksiyonu siler.

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

Bir koleksiyondaki birden çok BSO'yu tek bir istekle siler.

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

kimlikler : sağlanan virgülle ayrılmış listede kimlikleri olan koleksiyondaki BSO'ları siler. Maksimum 100 kimlik sağlanabilir.

Verilen konumdaki BSO'yu siler.

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

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


Bu iyi bir çözüm gibi görünüyor . Sanırım mozilla doğru olduğunu düşünüyorsa o zaman doğru olmalı? O zaman tek soru hata işlemedir. Varsayalım ki? İds = 1,2,3 geçtiler ve id 3 mevcut değil 1 ve 2'yi silip sonra 200 ile yanıt verir misiniz, çünkü talep eden 3'ün gitmesini istiyor ve orada değil, bu yüzden önemli değil? ya da ya 1'i silme yetkisi varsa 2'yi değil ... hiçbir şeyi silip bir hatayla yanıt verir misiniz yoksa elinizden geleni silip diğerlerini mi bırakırsınız ...
tempcke

1
Genellikle başarılı bir yanıt döndürürüm çünkü son durum ne olursa olsun aynıdır. Bu, istemcideki mantığı da basitleştirir çünkü artık bu hata durumunu ele almak zorunda kalmazlar. Yetkilendirme davasına gelince, tüm talepte başarısız olurum ... ama gerçekten kullanım durumunuza bağlı.
Nathan Phetteplace

Nathan ile aynı fikirdeyim.
Nicholas Shanks

3

Bu, REST sözleşmesinin gri bir alanı gibi görünüyor.

Evet, şimdiye kadar toplu işlemlerden (toplu silme gibi) bahseden yalnızca bir REST API tasarım kılavuzuyla karşılaştım: google api tasarım kılavuzu .

Bu kılavuz , iki nokta üst üste kullanılarak bir kaynak aracılığıyla ilişkilendirilebilecek "özel" yöntemlerin oluşturulmasından bahseder , örneğin https://service.name/v1/some/resource/name:customVerb, kullanım durumu olarak toplu işlemlerden de açıkça bahsedilir:

Özel bir yöntem, bir kaynak, koleksiyon veya hizmet ile ilişkilendirilebilir. Keyfi bir istek alabilir ve rastgele bir yanıt döndürebilir ve ayrıca akış isteği ve yanıtı destekler. [...] Özel yöntemler, en esnek anlamlara sahip olduğu için HTTP POST fiilini kullanmalıdır [...] Performans açısından kritik yöntemler için, istek başına ek yükü azaltmak için özel toplu yöntemler sağlamak yararlı olabilir .

Böylece, Google'ın API kılavuzuna göre aşağıdakileri yapabilirsiniz:

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

... koleksiyon kaynağınızdaki bir grup öğeyi silmek için.


Öğe listesinin JSON formatlı bir dizi aracılığıyla iletilmesi uygun bir çözüm mü?
Daniele

Evet elbette. Kimliklerin bir json dizisi aracılığıyla gönderildiği bir yükü POST edebilirsiniz.
B12Toaster

Google API rehberinin 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,Özel Yöntem bölümünde söylendiğine dikkat çekiliyor. Ancak GET accounts.locations.batchGetapi, gövdeli GET yöntemidir. Bu tuhaf. developers.google.com/my-business/reference/rest/v4/…
鄭元傑

@ 鄭元傑 katılıyorum, ilk bakışta biraz tuhaf görünüyor, ancak yakından bakarsanız, aslında POSTkullanılan bir http yöntemi ve yalnızca özel yöntem adlandırılıyor batchGet. Sanırım Google, (a) tüm özel yöntemlerin olması gerektiği kuralına bağlı kalmak POST(cevabıma bakın) ve (b) insanların vücuda bir "filtre" koymasını kolaylaştırmak için yapıyor, böylece siz bunu yapmak zorunda değilsiniz filtreden çıkış veya sorgu dizelerinde olduğu gibi kodlama. Elbette olumsuz yanı, bunun artık gerçekten önbelleğe alınabilir olmaması ...
B12Toaster

https://service.name/v1/some/resource/name:customVerbtanım gereği RESTful değildir.
deamon

2

Bir koleksiyonun toptan olarak değiştirilmesine izin verdim, örneğin PUT ~/people/123/shoesbedenin koleksiyonun tamamı olduğu durumlarda.

Bu, istemcinin öğeleri gözden geçirmek ve bazılarını çıkarmak ve bazılarını eklemek ve ardından sunucuyu güncellemek istediği küçük alt öğe koleksiyonları için çalışır. Tümünü silmek için boş bir koleksiyon PUT yapabilirler.

Bu, GET ~/people/123/shoes/9bir PUT onu silmiş olsa bile hala önbellekte kalacağı anlamına gelir , ancak bu yalnızca bir önbelleğe alma sorunu ve başka bir kişi ayakkabıyı silerse bir sorun olur.

Verilerim / sistem API'lerim, sona erme sürelerinin aksine her zaman ETag'leri kullanır, böylece sunucu her istek üzerine vurulur ve verileri değiştirmek için doğru sürüm / eşzamanlılık başlıklarına ihtiyacım var. Salt okunur ve görünüm / rapor hizalı API'ler için, başlangıçtaki isabetleri azaltmak için sona erme sürelerini kullanıyorum, örneğin bir lider panosu 10 dakika için iyi olabilir.

Çok daha büyük koleksiyonlar için, örneğin ~/people, birden fazla silmeye ihtiyaç duymuyorum, kullanım durumu doğal olarak ortaya çıkmama eğilimindedir ve bu nedenle tek bir DELETE iyi çalışır.

Gelecekte, REST API'leri oluşturma ve denetim gibi aynı sorunları ve gereksinimleri karşılama konusundaki deneyimim sayesinde, yalnızca GET ve POST fiillerini kullanmaya ve olayların etrafında tasarım yapmaya meyilli olacağım, örneğin POST a adres değişikliği olayı, ancak bundan şüpheleniyorum Kendi problemleriyle gelecek :)

Ayrıca ön uç geliştiricilerin, katı "Fielding zealot" REST API tasarımlarından hoşlanmadıklarının pratik, geçerli müşteri tarafı nedenleri olduğundan ve üretkenlik ve önbellek katmanlama nedenleri.


Bu cevabı son cümleyi okuyana kadar sevdim :) Kesin REST uygulamasının net bir zararlı etkisi olduğu bir kullanım durumu görmedim. Elbette her iki uçta da daha fazla kod yazabilir, ancak daha güvenli, daha temiz ve daha az bağlı bir sistem elde edersiniz.
Nicholas Shanks

Haha. Aslında bir kalıp haline geldi! Ön uç için arka uç, buna ThoughtWorks teknoloji radarı denir. Ayrıca, JavaScript'te zahmetli olabilecek daha fazla uygulama mantığının yazılmasına izin verir ve açıkça bir istemci olmadan güncellenebilir, bu nedenle bir iOS uygulaması için güncelleme deyin.
Luke Puplett

Google'ın ilk dört isabetini gözden geçirerek, bu BFF tekniğinin yalnızca müşteriler kontrolünüz altındayken işe yarayabileceği görülüyor . İstemci geliştiricileri, gerçek arka uç olan mikro hizmet API'lerine çağrıları eşleyerek istedikleri API'yi geliştirir. Bu diyagramda: samnewman.io/patterns/architectural/bff/#bff "Çevre" çizgisini BFF kutularının altına yerleştirirdim - her kutu basitçe istemcinin bir parçasıdır. Mikro hizmetleri barındıran veri merkezinin dışında bile yaşayabilir. Ayrıca REST'in her iki arayüze (istemci / BFF ve BFF / mikro hizmet) nasıl uygulanmadığını da görmüyorum.
Nicholas Shanks

1
Evet bu iyi bir nokta. Genellikle, örneğin mikro hizmetler oluşturan bir ekip ve açısal uygulama yapan bir ekibiniz olduğunda ve bu geliştirme ekibi, bir grup küçük sadelik hizmetine karşı çalışmak zorunda kalmaktan hoşlanmayan daha ön uç tipler olduğunda içindir. Mikro hizmetleri ve kümelenmeyi müşterileriniz için daha kullanışlı bir cepheye soyutlamak için aynı modeli kullanamayacağınız için herhangi bir neden görmüyorum, öyle ki mikro hizmetler cepheyi etkilemeden değiştirilebilir.
Luke Puplett

Bir API uç noktası, etki alanının ve işletmenin ihtiyaçlarını modellemelidir. Bu sorunları çözmek için kodlayın ve aşırı mühendislikten kaçınarak katı ve çoğu zamanın esnek olmayan şartnamelerine uyun. REST zaten yönergelerden başka bir şey değildir.
Victorio Berra
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.