Key Condition Expression DynamoDB
Key condition expression adalah KeyConditionExpression yang Anda berikan ke sebuah Query — satu-satunya bagian request yang DynamoDB gunakan untuk menemukan item.
Segalanya yang lain (filter, projection) berjalan setelah pembacaan sudah dihitung.
Apa itu key condition expression di DynamoDB?
Sebuah key condition expression adalah KeyConditionExpression pada sebuah Query yang memberi tahu DynamoDB Item mana yang harus dibaca. harus berupa kesetaraan (PK = :v); mengambil satu operator range — =, <, <=, >, >=, BETWEEN, atau begins_with. Ia memutuskan apa yang dibaca dan ditagih, tidak seperti sebuah filter.
- harus berupa kesetaraan.
PK = :vdan tidak lebih — tanpa range, tanpabegins_with, tanpaIN. DynamoDB meng-hash-nya untuk menemukan satu partisi. - mengambil operator range.
=,<,<=,>,>=,BETWEEN, ataubegins_with— di sinilah Anda mengiris sebuah . - Ia bukan filter. Sebuah key condition memutuskan apa yang dibaca dan ditagih; sebuah
FilterExpressionhanya memangkas hasil setelah Anda membayar pembacaannya. - Sort key terurut byte. Operator range membandingkan secara leksikografis, jadi cara Anda memformat string sort key adalah kekuatan query Anda.
Mengapa partition key dikunci ke kesetaraan
DynamoDB menyimpan Item dengan meng-hash partition key ke partisi fisik. Sebuah hash memberi Anda satu lokasi, bukan range — jadi tidak ada yang bisa dipindai melintasi.
Itulah mengapa PK > :v atau begins_with(PK, :v) ditolak mentah-mentah. Mesinnya tidak bisa
menjawab "semua partisi yang key-nya dimulai dengan X" tanpa membaca seluruh tabel, yang
persis merupakan Scan yang dibangun untuk dihindarinya.
Datang dari SQL, ini terasa terbalik: WHERE id LIKE 'order%' sepele di Postgres. Di DynamoDB
partition key adalah sebuah alamat, bukan kolom yang bisa dicari.
Sort key adalah tempat kekuatan berada
Dalam satu partisi, Item disimpan terurut berdasarkan sort key. Pengurutan itulah yang dieksploitasi operator range — DynamoDB melompat ke sebuah posisi dan membaca maju.
| Operator | Membaca | Gunakan untuk |
|---|---|---|
SK = :v | Satu Item persis | Anak spesifik berdasarkan key-nya |
SK < / <= / > / >= :v | Satu irisan terbuka | "Segalanya setelah titik ini" |
SK BETWEEN :a AND :b | Range tertutup (inklusif) | Jendela terbatas — range tanggal |
begins_with(SK, :p) | Irisan prefix | Tipe atau hierarki di bawah PK |
Tidak ada LIKE, tidak ada CONTAINS, tidak ada ENDS_WITH pada key. Pencocokan substring
dan sufiks tidak terurut byte, jadi mereka akan memaksa pembacaan penuh — secara desain, API
tidak akan membiarkan Anda. Pencocokan substring ada via contains() dalam sebuah
FilterExpression (di mana Anda sudah membayar pembacaannya); pencocokan sufiks tidak tersedia
di sisi server sama sekali — simpan key yang dibalik atau filter di sisi klien.
(AWS: Key condition expressions)
Contoh nyata: pesan dalam aplikasi chat
Katakanlah Anda membangun chat berbasis channel. Satu tabel, dipartisi berdasarkan channel, diurutkan berdasarkan waktu pesan. Key schema awal:
- Partition key
ChannelRef—CH#{channelId} - Sort key
PostedAt— timestamp ISO-8601,MSG#2026-06-23T14:05:00Z
Prefix MSG# menjaga baris pesan tetap dapat diurutkan dan berbeda dari tipe baris lain yang
mungkin Anda ko-lokasikan di bawah channel yang sama (config yang di-pin, keanggotaan).
Muat pesan terkini sebuah channel. Hanya partition key, terbaru dulu:
KeyConditionExpression ChannelRef = :ch
ExpressionAttributeValues { ":ch": "CH#general" }
ScanIndexForward false
ScanIndexForward: false menjelajahi koleksi yang terurut secara terbalik — cara murah untuk
mendapat "paling terkini dulu" tanpa mengurutkan di sisi klien.
Hari spesifik dengan begins_with. Karena timestamp adalah sort key dan disimpan sebagai
teks, prefix tanggal adalah irisan yang bersih:
KeyConditionExpression ChannelRef = :ch AND begins_with(PostedAt, :day)
:ch "CH#general"
:day "MSG#2026-06-23"
Itu membaca setiap pesan pada 2026-06-23 dan tidak lain — DynamoDB melompat ke prefix dan berhenti saat jatuh dari ujung. Ini hanya bekerja karena prefix adalah left-anchor sejati dari string yang terurut byte.
Jendela presisi dengan BETWEEN. Untuk "pesan selama jam 14:00", sebuah range inklusif
mengalahkan prefix:
KeyConditionExpression ChannelRef = :ch AND PostedAt BETWEEN :lo AND :hi
:ch "CH#general"
:lo "MSG#2026-06-23T14:00:00Z"
:hi "MSG#2026-06-23T14:59:59Z"
BETWEEN inklusif pada kedua batas, jadi pilih endpoint Anda dengan sengaja — sebuah
off-by-one di sini diam-diam menjatuhkan atau menggandakan pesan tepi.
Anda bisa merangkai dan menyalin salah satu expression ini, dengan map
ExpressionAttributeValues yang terisi untuk Anda, di
expression builder DynamoDB — praktis untuk mendapatkan
sintaks begins_with dan BETWEEN benar pada percobaan pertama.
Builder ini di-preset ke query pk = … AND begins_with(sk, …) — ubah operatornya untuk
melihat KeyConditionExpression diperbarui:
Lihat di DynoTable
Jalankan key condition yang sama terhadap partisi channel nyata. Begitu Anda mengatur filter
partition-key, DynoTable menerbitkan sebuah Query — jadi Anda memuat hanya irisan itu, bukan
seluruh koleksi.
Jebakannya: mengacaukan key condition dengan filter
Kesalahan yang mahal adalah meraih FilterExpression untuk melakukan tugas sebuah key. Sebuah
filter bahkan tidak bisa mereferensikan PostedAt — ia adalah sort key, dan DynamoDB menolak
filter pada atribut key dengan ValidationException. Jadi workaround-nya adalah menduplikasi
tanggal ke atribut non-key biasa (MessageDate) dan memfilter pada itu:
KeyConditionExpression ChannelRef = :ch
FilterExpression begins_with(MessageDate, :day)
Ini terlihat setara dengan key condition begins_with di atas dan mengembalikan baris yang
sama — tetapi ia membaca seluruh partisi channel dulu, lalu membuang segalanya di luar
harinya. Anda ditagih untuk pembacaan penuh.
Filter tidak pernah mengurangi biaya baca. Mereka berjalan setelah DynamoDB menghitung
Item-nya, bumerang yang sama dengan sebuah Scan yang difilter. Jika
sebuah predikat bisa masuk ke key condition, di sanalah tempatnya.
Perbaikannya di hulu: jika sebuah pola akses tidak bisa diekspresikan sebagai satu kesetaraan PK plus sebuah range sort-key, itu sinyal pemodelan. Entah bentuk ulang sort key-nya, atau tambahkan indeks yang di-key untuk pola itu — lihat GSI vs LSI dan single-table design untuk cara menata key-nya.
Jebakan dan langkah selanjutnya
- Partition key selalu
=. Tanpa range, selamanya. Jika Anda butuh range melintasi partisi, Anda sudah melampaui satuQuery. - Satu kondisi sort-key per query. Anda tidak bisa
ANDdua predikat sort-key; pilihBETWEENataubegins_with, bukan keduanya. - Reserved word butuh alias. Key bernama
TimestampatauNameharus memakaiExpressionAttributeNames(#ts), atau query error. (AWS: reserved words) BETWEENinklusif. Kedua endpoint dicocokkan — desain batas Anda sesuai itu.
Draf key condition Anda di expression builder, lalu coba DynoTable untuk menjalankannya terhadap tabel Anda sendiri dan melihat persis irisan mana yang dikembalikan setiap key condition.