DynamoDB'de Expression Attribute Name'leri ve Value'ları
DynamoDB ifadeleri şablonlardır: placeholder'lar yazarsın, sonra gerçek attribute
adlarını ve değerlerini iki yan eşlemede sağlarsın. #name bir ad placeholder'ıdır;
:value bir değer placeholder'ıdır. İkisini karıştır, DynamoDB tüm çağrıyı reddeder.
DynamoDB'de #name ile :value arasındaki fark nedir?
#name, ExpressionAttributeNames aracılığıyla sağlanan bir attribute adı placeholder'ıdır; :value ise ExpressionAttributeValues aracılığıyla sağlanan bir attribute değeri placeholder'ıdır. Rezerve kelimeleri, noktaları veya boşlukları atlatmak için #name, her literal için ise :value kullan — DynamoDB değerleri asla satır içine (inline) koymaz. İkisi birbirinin yerine kullanılamaz; bunları yer değiştirmek bir ValidationException fırlatır.
#namebir attribute adını ikame ederExpressionAttributeNamesaracılığıyla — bir attribute bir rezerve kelimeyle çakıştığında veya bir nokta/boşluk içerdiğinde kullan.:valuebir değeri ikame ederExpressionAttributeValuesaracılığıyla — DynamoDB literal'leri asla ifade metnine satır içi (inline) koymaz, bu yüzden her değer bir placeholder'dır.- Birbirleriyle değiştirilemezler. Bir
:'nin ait olduğu yerde bir#, sessiz bir işlemsiz (no-op) değil, birValidationException'dır.
SQL'den gelince, ikisini de satır içi koyarsın — WHERE status = 'published'.
DynamoDB hiçbirini satır içi koymaz. O ayrım, her yeni geleni yanıltan şeydir.
İki eşleme neden vardır
SQL'de sorgu dizesi her şeyi taşır: sütun adları, literal'ler, operatörler. DynamoDB ifadenin şeklini verisinden kasıtlı olarak ayırır.
Değerler kendi eşlemelerine girer, böylece DynamoDB her birini tipleyebilir (S, N,
BOOL, …) ve ayrıştırıcı bir string'in nerede bittiğini asla tahmin etmek zorunda
kalmaz — yanlış yapılacak bir tırnak veya kaçış yoktur. Tam tür-etiketi listesi için
bkz. DynamoDB'de veri türleri.
Adlar aynı muameleyi farklı bir nedenle alır: DynamoDB'nin uzun bir rezerve kelime listesi vardır ve biriyle eşleşen herhangi bir attribute, bir ifadede çıplak bir ad olarak görünemez. Placeholder rezervasyonu tamamen atlatır.
Rezerve-kelime tuzağı
İşte bir CMS makaleler tablosu — partition key BLOG#<blog>, sort key
ARTICLE#<slug> — attribute'ları doğal okunan ama rezerve kelimelerle çakışan:
| Attribute | Rezerve mi? | Ne tutar |
|---|---|---|
status | evet | draft / published |
name | evet | yazar görünen adı |
size | evet | render edilmiş byte uzunluğu |
ttl | evet | arşiv sona erme (epoch) |
slug | hayır | URL slug'ı |
status, name, size ve ttl'nin hepsi AWS'nin rezerve-kelimeler listesindedir,
bu yüzden bu filtre ilk kelimede başarısız olur:
FilterExpression status = :s
DynamoDB bir ValidationException döndürür — "Attribute name is a reserved keyword;
reserved keyword: status". Düzeltme bir ad placeholder'ıdır, asla attribute'u yeniden
adlandırmak değil:
FilterExpression #status = :s
ExpressionAttributeNames { "#status": "status" }
ExpressionAttributeValues { ":s": { "S": "published" } }
Tuzak: slug rezerve değildir, bu yüzden slug'a karşı test ettiğin bir sorgu
çalışır ve bir sonrakinin de çalışacağını varsayarsın. Sonra status onu bozar. Tam
liste değişir, bu yüzden onu ezberleme — her adı placeholder ile koru ve asla
ısırılmazsın.
Her değeri haritala, her zaman
Değerler pazarlık konusu değildir: satır içi bir literal için söz dizimi yoktur. Düz bir sayı bile bir placeholder alır. Bu güncelleme bir makaleyi yayınlanmış olarak işaretler, boyutunu damgalar ve 30 günlük bir arşiv TTL'si ayarlar:
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" }
}:sz ve :exp'nin N string'leri olarak gönderildiğine dikkat et — DynamoDB'nin sayı
türü tel üzerinde bir string olarak kodlanır. Değer eşlemesi aynı zamanda bir değeri
cümleler arasında yeniden kullandığın yerdir: :s'yi bir kez tanımla, ona hem bir
ConditionExpression'da hem de bir FilterExpression'da referans ver.
Bu iki eşlemeyi elle oluşturmak, yazım hatalarının saklandığı yerdir. Expression Builder, ifade dizesini ve her iki eşlemeyi birlikte, tür etiketleri doldurulmuş olarak üretir, böylece placeholder'lar senkronizasyondan çıkamaz.
İç içe ve sorunlu yollar için adlar
# placeholder'ı rezerve kelimeleri atlatmaktan fazlasını yapar. Doküman-yolu söz
dizimi noktalar ve köşeli parantezler kullanır, bu yüzden tam anlamıyla bir nokta
içeren bir attribute — diyelim ki bir metadata anahtarı og.title — bir placeholder
olmadan adreslenemez:
ProjectionExpression #og
ExpressionAttributeNames { "#og": "og.title" }
Onsuz, DynamoDB og.title'ı "og map'i içindeki title alanı" olarak okur — tamamen
farklı bir şey. Boşluklu veya başında rakam olan adlar için de aynı hikaye. İç içe
geçme için, her segmenti placeholder ile korursun: hem #meta hem de #author
tanımlı olarak #meta.#author.
Adlar ve değerler, yan yana
#name | :value | |
|---|---|---|
| İkame ettiği | bir attribute adı | bir attribute değeri |
| Eşleme | ExpressionAttributeNames | ExpressionAttributeValues |
| Önek | # | : |
| Gereken durum | rezerve kelimeler, noktalar, boşluklar | her zaman — satır içi literal yok |
| Yanlış olan hata verir | ValidationException | ValidationException |
Bir değer bir ad olarak tiplenseydi, DynamoDB published adlı bir attribute arardı ve
koşulun kastettiğin şekilde asla eşleşmezdi — bu yüzden API sessizce yanlış olmak yerine
yüksek sesle başarısız olur. O katılık bir özelliktir: sessiz bir yanlış cevap yoktur.
Tuzaklar ve sonraki adımlar
- Kullanmadığın bir placeholder bildirmek — DynamoDB her iki eşlemede de kullanılmayan girişleri reddeder. Eşlemeleri ifadeden oluştur, ondan önce değil.
- İfadeyi düzenledikten sonra
:v'yi yeniden kullanmak — bir cümleyi düşür ve değeri oyalanabilir, kullanılmayan-giriş hatasını tetikler. Builder onları senkronize tutar. - Bir kez işe yaradığı için bir adın güvenli olduğunu varsaymak — rezerve-kelime çakışmaları attribute başınadır. Tek tip placeholder kullan ve tahmin etmeyi bırak.
Bu eşlemeler her yazma yolunda görünür, bu yüzden single-table tasarım ile ve bir filtre eklemeden önce ne zaman Query ne zaman Scan yapacağını bilmekle doğal olarak eşleşirler.
İfadeyi artı her iki eşlemeyi Expression Builder ile üret, sonra onları kendi tablolarına karşı çalıştırmak ve placeholder'ların çözüldüğünü izlemek için DynoTable'ı dene.