Menengah4 menit baca

Update Expression DynamoDB

Sebuah update expression memberi tahu UpdateItem cara memutasi satu Item: atribut mana yang ditulis, dinaikkan, dihapus, atau dilipat ke dalam sebuah set. Tidak ada UPDATE … SET … WHERE — Anda menamai Item dengan keynya dan mendeskripsikan perubahan dengan empat keyword klausa.

Bagaimana cara kerja update expression DynamoDB?

Update expression DynamoDB memberi tahu UpdateItem cara memutasi satu item menggunakan empat klausa. SET menulis atau menimpa . ADD menaikkan angka secara atomik atau melakukan union ke dalam set. REMOVE menghapus atribut atau satu elemen list. DELETE menghapus member tertentu dari sebuah set. Satu panggilan dapat membawa keempat klausa sekaligus.

  • SET menulis atau menimpa atribut — skalar, dokumen, dan idiom fungsi if_not_exists serta list_append.
  • ADD melakukan increment angka atomik atau union set, dalam satu round trip, tanpa baca-dulu.
  • REMOVE menghapus atribut sepenuhnya (atau satu elemen list berdasarkan index).
  • DELETE menghapus member tertentu dari sebuah set — dan hanya dari sebuah set.

Datang dari SQL, jebakannya adalah meraih SET untuk segalanya. ADD dan DELETE ada karena read-modify-write pada counter atau set adalah race yang akan Anda kalahi di bawah concurrency.

Pilih klausa berdasarkan apa yang Anda ubah

Satu panggilan UpdateItem bisa membawa keempat klausa sekaligus, dalam urutan SET … REMOVE … ADD … DELETE. Setiap keyword muncul paling banyak sekali dan mengambil daftar aksi yang dipisah koma.

KlausaBekerja padaGunakan untuk
SETAtribut apa punMenulis/menimpa nilai atau field dokumen
ADDNumber atau Set sajaMenaikkan secara atomik, atau union ke set
REMOVEAtribut atau elemen list apa punMenghapus atribut; menjatuhkan satu index list
DELETESet sajaMenghapus member tertentu dari sebuah set

ADD pada string dan DELETE pada skalar adalah error validasi, bukan no-op — DynamoDB menolak seluruh panggilan. Menurut referensi update-expression AWS, ADD dibatasi pada number dan set, dan DELETE pada set.

Contoh nyata: keranjang belanja

Satu Item per keranjang, berkey CartPK = "CART#c-9f21" dan CartSK = "SUMMARY". Ia melacak OrderTotal berjalan, sebuah list LineItems, string set PromoCodes, dan sebuah ItemCount.

SET — menulis skalar dan dokumen

SET menimpa apa pun yang ada di sana. Tambahkan line item ke list dan naikkan total dalam panggilan yang sama:

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

list_append(LineItems, :newItem) menambahkan ke ekor; balik argumennya — list_append(:newItem, LineItems) — untuk menambahkan ke depan. Urutan argumen adalah urutan konkatenasi, tak lebih dari itu.

Ada footgun di panggilan pertama itu: jika keranjangnya baru, LineItems belum ada, dan list_append pada atribut yang hilang gagal. Jaga dengan if_not_exists:

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

if_not_exists(LineItems, :empty) mengembalikan list saat ini jika ada, kalau tidak fallback :empty (list kosong []). Itu membuat add pertama dan setiap add berikutnya memakai expression yang sama — alasan nyata idiom ini ada.

ADD — naikkan count, secara atomik

Untuk menaikkan ItemCount, jangan membacanya, menambah satu di kode Anda, lalu SET ia kembali. Itu lost-update race: dua add bersamaan keduanya membaca 3, keduanya menulis 4, dan Anda kehilangan satu. ADD melakukan aritmetika di sisi server:

ADD ItemCount :one

Dengan :one = 1, ini adalah counter atomik. Panggilan bersamaan terserialisasi pada Item, jadi dua add mendarat sebagai +2. Lewatkan angka negatif untuk mengurangi. Jika ItemCount absen, ADD memperlakukannya sebagai 0 lebih dulu — jadi Anda tak perlu menyemai counter-nya.

Anda bisa membangun expression persisnya — nama, nilai bertipe, dan request yang ter-marshal — di DynamoDB expression builder tanpa meng-escape tangan satu pun placeholder #name atau :value.

REMOVE — jatuhkan atribut atau satu line item

REMOVE adalah cara Anda menghapus atribut sepenuhnya (tak ada "set ke null" — itu hanya menulis tipe NULL). Bersihkan diskon yang diterapkan dan jatuhkan line item ketiga dalam satu panggilan:

REMOVE AppliedDiscount, LineItems[2]

LineItems[2] menghapus elemen di index 2 dan menggeser segalanya setelahnya ke bawah — index 3 menjadi 2, dan seterusnya. Jika Anda REMOVE dua index dalam satu expression, keduanya dievaluasi terhadap list asli, jadi menghapus [2] dan [3] bersama menjatuhkan elemen ketiga dan keempat seperti yang Anda harapkan.

DELETE — hapus member set

PromoCodes adalah string set, jadi customer yang menarik satu kode memakai DELETE, bukan REMOVE. REMOVE PromoCodes akan melenyapkan seluruh set; DELETE mengurangkan member yang disebut:

DELETE PromoCodes :pulled

Dengan :pulled = set {"SAVE10"}, hanya member itu yang pergi. Dua aturan menggigit di sini: sebuah set tak pernah boleh kosong, jadi menghapus member terakhir menghapus atribut PromoCodes sepenuhnya; dan nilainya harus berupa tipe set yang cocok dengan atributnya — string telanjang adalah type error.

Satukan

Sebuah update "tambah item, terapkan promo, naikkan count" adalah satu panggilan melintasi tiga klausa:

SET LineItems = list_append(if_not_exists(LineItems, :empty), :newItem),
OrderTotal = OrderTotal + :price
ADD ItemCount :one
DELETE PromoCodes :expiredCode

Perhatikan OrderTotal = OrderTotal + :price — aritmetika di dalam SET bekerja pada nilai yang ada. Ia tak atomik sebagaimana ADD untuk keamanan-race, tetapi ia membaca total saat ini di sisi server alih-alih round-trip ia lewat kode Anda.

Jebakan yang harus dihindari

  • Meng-SET counter yang Anda baca dulu. Gunakan ADD — read-modify-write kehilangan pembaruan di bawah concurrency. Ini bug keranjang/inventory paling umum.
  • list_append pada list yang hilang. Bungkus target dengan if_not_exists atau penulisan pertama gagal.
  • Mengelirukan REMOVE dan DELETE. REMOVE menjatuhkan atributnya; DELETE mengurangkan member dari sebuah set. Mencampurnya menghapus lebih dari yang Anda maksud.
  • Melupakan UpdateItem adalah upsert. Jika key-nya tak ada, ia membuat Item. Gunakan ConditionExpression (attribute_exists(CartPK)) saat Anda bermaksud "perbarui saja".

Untuk memodelkan key yang dijalani expression ini, lihat single-table design; untuk memutuskan cara Anda membaca kembali keranjang, lihat query vs scan.

Bangun dan salin salah satunya di expression builder, lalu coba DynoTable untuk menjalankannya terhadap tabel Anda sendiri dan menyaksikan Item berubah secara langsung.

Diperbarui