Expression Attribute Name dan Value di DynamoDB
Expression DynamoDB adalah template: Anda menulis placeholder, lalu memasok nama
atribut dan nilai nyata dalam dua peta samping. #name adalah placeholder nama;
:value adalah placeholder nilai. Kelirukan keduanya dan DynamoDB menolak seluruh
panggilan.
Apa beda antara #name dan :value di DynamoDB?
#name adalah placeholder untuk nama atribut, dipasok lewat
ExpressionAttributeNames; :value adalah placeholder untuk nilai atribut,
dipasok lewat ExpressionAttributeValues. Pakai #name untuk mengelak dari
reserved word, titik, atau spasi, dan :value untuk setiap literal — DynamoDB
tak pernah meng-inline nilai. Keduanya tak dapat dipertukarkan; menukarnya
memunculkan ValidationException.
#namemenggantikan nama atribut lewatExpressionAttributeNames— gunakan ia setiap kali sebuah atribut bentrok dengan reserved word atau mengandung titik/spasi.:valuemenggantikan nilai lewatExpressionAttributeValues— DynamoDB tak pernah meng-inline literal ke dalam teks expression, jadi setiap nilai adalah placeholder.- Mereka tak dapat dipertukarkan. Sebuah
#di tempat:seharusnya adalahValidationException, bukan no-op senyap.
Datang dari SQL, Anda meng-inline keduanya — WHERE status = 'published'. DynamoDB
tak meng-inline satu pun. Pemisahan itulah yang membingungkan setiap pendatang baru.
Mengapa kedua peta ada
Di SQL string query membawa segalanya: nama kolom, literal, operator. DynamoDB secara sengaja memisahkan bentuk expression dari data-nya.
Nilai masuk ke petanya sendiri agar DynamoDB bisa menentukan tipe masing-masing
(S, N, BOOL, …) dan agar parser tak pernah harus menebak di mana sebuah string
berakhir — tak ada quoting atau escaping untuk salah. Lihat
tipe data di DynamoDB untuk daftar type-tag lengkapnya.
Nama mendapat perlakuan sama dengan alasan berbeda: DynamoDB punya daftar panjang reserved word, dan atribut mana pun yang cocok dengan satu tak bisa muncul sebagai nama telanjang dalam expression. Placeholder mengelak dari reservasi sepenuhnya.
Jebakan reserved-word
Ini sebuah tabel artikel CMS — partition key BLOG#<blog>, sort key
ARTICLE#<slug> — yang atributnya terbaca alami tetapi kebetulan bentrok dengan
reserved word:
| Atribut | Reserved? | Apa yang ia tampung |
|---|---|---|
status | ya | draft / published |
name | ya | nama tampilan penulis |
size | ya | panjang byte ter-render |
ttl | ya | kedaluwarsa arsip (epoch) |
slug | tidak | URL slug |
status, name, size, dan ttl semuanya ada di daftar reserved-word AWS, jadi
filter ini gagal pada kata pertama:
FilterExpression status = :s
DynamoDB mengembalikan ValidationException — "Attribute name is a reserved
keyword; reserved keyword: status". Solusinya adalah placeholder nama, jangan
pernah merename atributnya:
FilterExpression #status = :s
ExpressionAttributeNames { "#status": "status" }
ExpressionAttributeValues { ":s": { "S": "published" } }
Jebakannya: slug tidak reserved, jadi query yang Anda uji terhadap slug
bekerja, dan Anda berasumsi yang berikutnya juga begitu. Lalu status
merusaknya. Daftar lengkapnya bergerak, jadi jangan menghafalnya — placeholder-kan
setiap nama dan Anda tak pernah digigit.
Petakan setiap nilai, selalu
Nilai tak bisa ditawar: tak ada sintaks untuk literal inline. Bahkan angka biasa mendapat placeholder. Update ini menandai sebuah artikel published, mencap ukurannya, dan menyetel TTL arsip 30-hari:
UpdateExpression: SET #status = :s, #size = :sz, #ttl = :exp
ExpressionAttributeNames: { "#status": "status", "#size": "size", "#ttl": "ttl" }
ExpressionAttributeValues: {
":s": { "S": "published" },
":sz": { "N": "20480" },
":exp": { "N": "1719792000" }
}Perhatikan :sz dan :exp dikirim sebagai string N — tipe number DynamoDB
ter-encode di kabel sebagai string. Peta nilai juga tempat Anda menggunakan ulang
sebuah nilai lintas klausa: definisikan :s sekali, referensikan ia di
ConditionExpression dan FilterExpression.
Membangun kedua peta ini dengan tangan adalah tempat typo bersembunyi. Expression Builder menghasilkan string expression dan kedua peta bersama, dengan type tag terisi, jadi placeholder tak bisa melenceng dari sinkron.
Nama untuk path bersarang dan janggal
Placeholder # melakukan lebih dari sekadar mengelak reserved word. Sintaks
document-path memakai titik dan kurung, jadi atribut yang secara harfiah mengandung
titik — misalnya key metadata og.title — tak dapat dialamati tanpa placeholder:
ProjectionExpression #og
ExpressionAttributeNames { "#og": "og.title" }
Tanpa itu, DynamoDB membaca og.title sebagai "field title di dalam map og" —
hal yang sama sekali berbeda. Cerita yang sama untuk nama dengan spasi atau angka di
depan. Untuk bersarang, Anda placeholder-kan setiap segmen: #meta.#author dengan
#meta dan #author keduanya terdefinisi.
Nama vs nilai, berdampingan
#name | :value | |
|---|---|---|
| Menggantikan | sebuah nama atribut | sebuah nilai atribut |
| Peta | ExpressionAttributeNames | ExpressionAttributeValues |
| Prefiks | # | : |
| Dibutuhkan untuk | reserved word, titik, spasi | selalu — tanpa literal inline |
| Yang salah error | ValidationException | ValidationException |
Jika sebuah nilai diketik sebagai nama, DynamoDB akan mencari atribut bernama
published dan kondisi Anda tak pernah cocok dengan cara yang Anda maksud — jadi API
gagal keras alih-alih. Kekakuan itu adalah fitur: tak ada jawaban salah yang senyap.
Jebakan dan langkah berikutnya
- Mendeklarasikan placeholder yang tak Anda pakai — DynamoDB menolak entri tak terpakai di salah satu peta. Bangun peta dari expression, bukan mendahuluinya.
- Menggunakan ulang
:vsetelah mengedit expression — jatuhkan sebuah klausa dan nilainya bisa tertinggal, memicu error entri-tak-terpakai. Builder menjaganya selangkah. - Mengasumsikan nama aman karena pernah bekerja — bentrokan reserved-word bersifat per-atribut. Placeholder-kan secara seragam dan berhenti menebak.
Peta ini muncul di setiap jalur tulis, jadi mereka berpasangan alami dengan single-table design dan dengan mengetahui kapan harus Query vs Scan sebelum Anda pernah melampirkan sebuah filter.
Hasilkan expression plus kedua peta dengan Expression Builder, lalu coba DynoTable untuk menjalankannya terhadap tabel Anda sendiri dan menyaksikan placeholder teresolusi.