Orta5 dakikalık okuma

DynamoDB Update Expression'lar: SET, REMOVE, ADD, DELETE (Örneklerle)

Bir update expression, UpdateItem'a tek bir öğeyi nasıl değiştireceğini söyler: hangi yazılacağını, artırılacağını, silineceğini ya da bir kümeye katılacağını. Çok satırlı bir UPDATE … SET … WHERE yoktur — tek bir öğeyi tam anahtarıyla adlandırır ve değişikliği dört yan tümce anahtar kelimesiyle tarif edersiniz.

DynamoDB update expression'lar nasıl çalışır?

Bir DynamoDB update expression, UpdateItem'a dört yan tümce kullanarak tek bir öğeyi nasıl değiştireceğini söyler. SET bir yazar ya da üzerine yazar. ADD bir sayıyı atomik olarak artırır veya bir kümeyle birleşim alır. REMOVE bir attribute'u ya da bir liste elemanını siler. DELETE bir kümeden belirli üyeleri çıkarır. Tek bir çağrı dördünü birden taşıyabilir.

  • SET bir attribute yazar ya da üzerine yazar — skalerler, dokümanlar ve if_not_exists ile list_append fonksiyon deyimleri.
  • ADD tek gidiş-dönüşte, önce okumadan, atomik bir sayı artırımı ya da küme birleşimi yapar.
  • REMOVE bir attribute'u tamamen siler (ya da tek bir liste elemanını indeksine göre).
  • DELETE bir kümeden belirli üyeleri çıkarır — ve yalnızca kümeden.

SQL'den gelirken tuzak, her şey için SET'e uzanmaktır. ADD ve DELETE var, çünkü bir sayaçta ya da kümede oku-değiştir-yaz, eşzamanlılık altında kaybedeceğiniz bir yarıştır.

Yan tümceyi değiştirdiğiniz şeye göre seçin

Tek bir UpdateItem çağrısı dört yan tümceyi de aynı anda ve herhangi bir sırada taşıyabilir. Her anahtar kelime en fazla bir kez görünür ve virgülle ayrılmış bir eylem listesi alır.

Yan tümceNeyde çalışırNe için kullanılır
SETHerhangi bir attributeBir değeri ya da doküman alanını yaz/üzerine yaz
ADDYalnızca Number veya SetAtomik artır ya da bir kümeyle birleşim al
REMOVEHerhangi bir attribute veya liste ögesiBir attribute'u sil; tek bir liste indeksini düşür
DELETEYalnızca SetBir kümeden belirli üyeleri çıkar

Bir string üzerinde ADD ve bir skaler üzerinde DELETE işlem yapmama değil, doğrulama hatasıdır — DynamoDB çağrının tamamını reddeder. AWS update expression referansına göre ADD sayılar ve kümelerle, DELETE ise kümelerle sınırlıdır.

İşlenmiş örnek: bir alışveriş sepeti

Sepet başına tek öğe; CartPK = "CART#c-9f21" ve CartSK = "SUMMARY" ile anahtarlanmış. Yürüyen bir OrderTotal, bir LineItems listesi, bir PromoCodes string kümesi ve bir ItemCount tutuyor.

SET — skalerleri ve dokümanları yazın

SET orada ne varsa üzerine yazar. Listeye bir kalem ekleyin ve aynı çağrıda toplamı yükseltin:

SET OrderTotal = :total,
LineItems = list_append(LineItems, :newItem),
UpdatedAt = :now

list_append(LineItems, :newItem) sona ekler; argümanları ters çevirin — list_append(:newItem, LineItems) — başa eklersiniz. Argüman sırası birleştirme sırasıdır, o kadar.

O ilk çağrıda bir tuzak var: sepet yepyeniyse LineItems henüz mevcut değildir ve olmayan bir attribute üzerinde list_append başarısız olur. Bunu if_not_exists ile koruyun:

SET LineItems = list_append(if_not_exists(LineItems, :empty), :newItem)

if_not_exists(LineItems, :empty), varsa mevcut listeyi, yoksa yedek :empty değerini (boş bir liste []) döndürür. Bu, ilk eklemenin de sonraki her eklemenin de aynı ifadeyi kullanmasını sağlar — bu deyimlerin var olmasının gerçek nedeni.

ADD — sayıyı atomik olarak artırın

ItemCount değerini yükseltmek için onu okuyup kodunuzda bir ekleyip geri SET yapmayın. Bu kayıp güncelleme yarışıdır: eşzamanlı iki ekleme de 3 okur, ikisi de 4 yazar ve birini düşürmüş olursunuz. ADD aritmetiği sunucu tarafında yapar:

ADD ItemCount :one

:one = 1 ile bu bir atomik sayaçtır. Eşzamanlı çağrılar öğe üzerinde sıraya girer, yani iki ekleme +2 olarak düşer. Azaltmak için negatif bir sayı geçirin. ItemCount yoksa ADD onu önce 0 kabul eder — yani sayacı hiç tohumlamanız gerekmez.

us-east-1 bölgesinde on-demand modda her ADD, yazmadan sonraki öğe boyutu üzerinden KB başına 1 WCU faturalandırır (yukarı yuvarlanarak). Tek bir ADD ItemCount :one içeren 1 KB'lık bir sepet özeti 1 WCU tutar — aynı satır oku-değiştir-yaz bir SET ile de aynı WCU'yu tutardı, ama eşzamanlılık altında kaybederdi. Öğeyi öğe boyutu hesaplayıcısında boyutlandırın.

Bu ifadenin tam olarak aynısını — adlar, türlü değerler ve hazırlanmış istek — tek bir #name ya da :value yer tutucusunu elle kaçırmadan DynamoDB expression builder içinde kurabilirsiniz.

Aşağıdaki hazır ayarı düzenleyin — bir SET artı atomik bir ADD — ve siz yazdıkça UpdateExpression'ın yeniden kuruluşunu izleyin:

İsteğini oluştur
Oluşturulan kod
new UpdateItemCommand({
  "TableName": "AuditLog",
  "Key": {
    "pk": {
      "S": "TENANT#acme"
    },
    "sk": {
      "S": "CONFIG"
    }
  },
  "UpdateExpression": "SET #upd0 = :updValue0 ADD #upd1 :updValue1",
  "ExpressionAttributeNames": {
    "#upd0": "plan",
    "#upd1": "seats"
  },
  "ExpressionAttributeValues": {
    ":updValue0": {
      "S": "pro"
    },
    ":updValue1": {
      "N": "5"
    }
  }
})

REMOVE — bir attribute'u ya da tek bir kalemi düşürün

Bir attribute'u tamamen silmenin yolu REMOVE'dur ("null'a ayarla" diye bir şey yok — o sadece NULL türünde bir değer yazar). Uygulanmış bir indirimi temizleyin ve üçüncü kalemi tek çağrıda düşürün:

REMOVE AppliedDiscount, LineItems[2]

LineItems[2], 2. indeksteki elemanı kaldırır ve ondan sonraki her şeyi aşağı kaydırır — indeks 3, 2 olur ve böyle sürer. Tek bir ifadede iki indeksi REMOVE ederseniz, ikisi de orijinal listeye karşı değerlendirilir; yani [2] ile [3] birlikte kaldırıldığında beklediğiniz gibi üçüncü ve dördüncü eleman düşer.

DELETE — küme üyelerini çıkarın

PromoCodes bir string kümesidir, dolayısıyla bir kodu geri çeken müşteri REMOVE değil DELETE kullanır. REMOVE PromoCodes kümenin tamamını yok ederdi; DELETE adlandırılan üyeleri çıkarır:

DELETE PromoCodes :pulled

:pulled = {"SAVE10"} kümesi olduğunda yalnızca o üye gider. Burada iki kural devreye girer: bir küme asla boş olamaz, dolayısıyla son üyeyi silmek PromoCodes attribute'unu tamamen kaldırır; ve değerin, attribute ile eşleşen bir küme türü olması gerekir — çıplak bir string tür hatasıdır.

Hepsini bir araya getirin

"Kalem ekle, promosyon uygula, sayacı yükselt" güncellemesi üç yan tümceye yayılan 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 ifadesine dikkat — SET içindeki aritmetik mevcut değer üzerinde çalışır. Bu da ADD kadar atomik ve yarışa dayanıklıdır: DynamoDB OrderTotal + :price ifadesini sunucu tarafında güncel değere karşı değerlendirir, yani eşzamanlı çağrılar kodunuzda gidiş-dönüş yapmak yerine öğe üzerinde sıraya girer.

Kaçınılması gereken tuzaklar

  • Önce okuduğunuz bir sayacı SET etmek. ADD kullanın — oku-değiştir-yaz, eşzamanlılık altında güncelleme kaybeder. Bu, en yaygın sepet/envanter hatasıdır.
  • Olmayan bir listede list_append. Hedefi if_not_exists ile sarın, yoksa ilk yazma başarısız olur.
  • REMOVE ile DELETE'i karıştırmak. REMOVE attribute'u düşürür; DELETE bir kümeden üye çıkarır. İkisini karıştırmak istediğinizden fazlasını siler.
  • UpdateItem'ın bir upsert olduğunu unutmak. Anahtar yoksa öğeyi oluşturur. "Yalnızca güncelle" demek istediğinizde bir ConditionExpression (attribute_exists(CartPK)) kullanın.

Bu ifadelerin üzerinde çalıştığı anahtarları modellemek için tek tablo tasarımı sayfasına; sepeti nasıl geri okuyacağınıza karar vermek için query ile scan sayfasına bakın.

Bunlardan herhangi birini expression builder içinde kurup kopyalayın, sonra kendi tablolarınıza karşı çalıştırıp öğenin canlı değişimini izlemek için DynoTable'ı deneyin.

Güncellendi