DynamoDB Update Expression'ları
Bir update expression, UpdateItem'a tek bir öğeyi nasıl mutasyona uğratacağını
söyler: hangi attribute'ları yazacağını, artıracağını, sileceğini veya bir set'e
katacağını. UPDATE … SET … WHERE yok — öğeyi anahtarıyla adlandırır ve değişikliği
dört cümle anahtar kelimesiyle tanımlarsın.
DynamoDB update expression'ları nasıl çalışır?
Bir DynamoDB update expression, UpdateItem'a dört cümle kullanarak tek bir öğeyi nasıl mutasyona uğratacağını söyler. SET bir yazar veya üzerine yazar. ADD atomik olarak bir sayıyı artırır ya da bir set'e birleştirir. REMOVE bir attribute'u veya bir liste elemanını siler. DELETE bir set'ten belirli üyeleri kaldırır. Tek bir çağrı dördünü birden taşıyabilir.
SETbir attribute'u yazar veya üzerine yazar — skalerler, dokümanlar veif_not_existsvelist_appendfonksiyon deyimleri.ADDtek bir turda, önce okumadan, atomik bir sayı artışı veya bir set birleşimi yapar.REMOVEbir attribute'u doğrudan siler (veya bir liste elemanını indeksiyle).DELETEbelirli üyeleri bir set'ten kaldırır — ve yalnızca bir set'ten.
SQL'den gelince, tuzak her şey için SET'e uzanmaktır. ADD ve DELETE, bir sayaç
veya bir set üzerinde oku-değiştir-yaz, eşzamanlılık altında kaybedeceğin bir yarış
olduğu için vardır.
Cümleyi değiştirdiğin şeye göre seç
Tek bir UpdateItem çağrısı dört cümlenin hepsini, SET … REMOVE … ADD … DELETE
sırasında, aynı anda taşıyabilir. Her anahtar kelime en fazla bir kez görünür ve
virgülle ayrılmış bir eylem listesi alır.
| Cümle | Üzerinde çalışır | Kullanım amacı |
|---|---|---|
SET | Herhangi bir attribute | Bir değer veya doküman alanı yaz/üzerine yaz |
ADD | Yalnızca Sayı veya Set | Atomik olarak artır veya bir set'e birleştir |
REMOVE | Herhangi bir attribute veya liste elemanı | Bir attribute'u sil; bir liste indeksini düşür |
DELETE | Yalnızca Set | Bir set'ten belirli üyeleri kaldır |
Bir string üzerinde ADD ve bir skaler üzerinde DELETE, işlemsiz (no-op) değil,
doğrulama hatalarıdır — DynamoDB tüm çağrıyı reddeder.
AWS update-expression referansına
göre, ADD sayılar ve set'lerle, DELETE ise set'lerle sınırlıdır.
İşlenmiş örnek: bir alışveriş sepeti
Sepet başına bir öğe, CartPK = "CART#c-9f21" ve CartSK = "SUMMARY" ile
anahtarlanmış. Çalışan bir OrderTotal, bir LineItems listesi, bir PromoCodes
string set'i ve bir ItemCount takip eder.
SET — skalerleri ve dokümanları yaz
SET, orada ne varsa üzerine yazar. Listeye bir satır öğesi ekle ve toplamı aynı
çağrıda artır:
SET OrderTotal = :total,
LineItems = list_append(LineItems, :newItem),
UpdatedAt = :now
list_append(LineItems, :newItem) kuyruğa ekler; argümanları ters çevir —
list_append(:newItem, LineItems) — başa eklemek için. Argümanların sırası,
birleştirmenin sırasıdır, fazlası değil.
O ilk çağrıda bir ayak tuzağı var: sepet yepyeniyse, LineItems henüz yoktur ve eksik
bir attribute üzerinde list_append başarısız olur. Onu if_not_exists ile koru:
SET LineItems = list_append(if_not_exists(LineItems, :empty), :newItem)
if_not_exists(LineItems, :empty), varsa mevcut listeyi, yoksa yedek :empty'yi
(boş bir liste []) döndürür. Bu, ilk eklemenin ve sonraki her eklemenin aynı ifadeyi
kullanmasını sağlar — bu deyimlerin var olmasının gerçek bir nedeni.
ADD — sayacı atomik olarak artır
ItemCount'u artırmak için, onu okuma, kodunda bir ekle ve geri SET etme. Bu bir
kayıp-güncelleme yarışıdır: iki eşzamanlı ekleme ikisi de 3 okur, ikisi de 4 yazar
ve birini düşürmüşsündür. ADD aritmetiği sunucu tarafında yapar:
ADD ItemCount :one
:one = 1 ile, bu atomik bir sayaçtır. Eşzamanlı çağrılar öğe üzerinde
sıralanır, böylece iki ekleme +2 olarak yer oturur. Azaltmak için negatif bir sayı
geç. ItemCount yoksa, ADD onu önce 0 olarak ele alır — bu yüzden sayacı asla
tohumlaman gerekmez.
Bu tam ifadeyi — adlar, tipli değerler ve marshal edilmiş istek —
DynamoDB expression builder'da tek bir #name
veya :value placeholder'ını elle kaçırmadan oluşturabilirsin.
REMOVE — bir attribute'u veya bir satır öğesini düşür
REMOVE, bir attribute'u tamamen sildiğin yoldur ("null'a ayarla" diye bir şey yok —
o sadece bir NULL türü yazar). Uygulanmış bir indirimi temizle ve üçüncü satır öğesini
tek bir çağrıda düşür:
REMOVE AppliedDiscount, LineItems[2]
LineItems[2], indeks 2'deki elemanı kaldırır ve ondan sonraki her şeyi aşağı
kaydırır — indeks 3, 2 olur, vesaire. Bir ifadede iki indeksi REMOVE edersen, ikisi
de orijinal listeye karşı değerlendirilir, bu yüzden [2] ve [3]'ü birlikte
kaldırmak, beklediğin gibi üçüncü ve dördüncü elemanları düşürür.
DELETE — set üyelerini kaldır
PromoCodes bir string set'idir, bu yüzden bir kod çeken bir müşteri REMOVE değil,
DELETE kullanır. REMOVE PromoCodes tüm set'i yok ederdi; DELETE adlandırılan
üyeleri çıkarır:
DELETE PromoCodes :pulled
:pulled = {"SAVE10"} set'i ile, yalnızca o üye gider. Burada iki kural ısırır: bir
set asla boş olamaz, bu yüzden son üyeyi silmek PromoCodes attribute'unu doğrudan
kaldırır; ve değer, attribute ile eşleşen bir set türü olmalıdır — çıplak bir string
bir tür hatasıdır.
Bir araya getir
Bir "öğe ekle, bir promosyon uygula, sayacı artır" güncellemesi, üç cümle boyunca tek bir çağrıdır:
SET LineItems = list_append(if_not_exists(LineItems, :empty), :newItem),
OrderTotal = OrderTotal + :price
ADD ItemCount :one
DELETE PromoCodes :expiredCode
OrderTotal = OrderTotal + :price'a dikkat et — SET içindeki aritmetik mevcut değer
üzerinde çalışır. ADD'in yarış-güvenliği için atomik olduğu gibi atomik değildir, ama
mevcut toplamı kodun üzerinden gidip getirmek yerine sunucu tarafında okur.
Kaçınılacak tuzaklar
- Önce okuduğun bir sayacı
SET-leme.ADDkullan — oku-değiştir-yaz, eşzamanlılık altında güncellemeleri kaybeder. Bu en yaygın sepet/envanter hatasıdır. - Eksik bir liste üzerinde
list_append. Hedefiif_not_existsile sar yoksa ilk yazma başarısız olur. REMOVEveDELETE'i karıştırma.REMOVEattribute'u düşürür;DELETEbir set'ten üyeleri çıkarır. Onları karıştırmak kastettiğinden fazlasını siler.UpdateItem'ın bir upsert olduğunu unutma. Anahtar yoksa, öğeyi oluşturur. "Yalnızca güncelle" demek istiyorsan birConditionExpression(attribute_exists(CartPK)) kullan.
Bu ifadelerin üzerinde çalıştığı anahtarları modellemek için, bkz. single-table tasarım; sepeti nasıl geri okuyacağına karar vermek için, bkz. query ve scan.
Bunlardan herhangi birini expression builder'da oluştur ve kopyala, sonra onları kendi tablolarına karşı çalıştırmak ve öğenin canlı değiştiğini izlemek için DynoTable'ı dene.