Orta4 dakikalık okuma

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.

  • #name bir attribute adını ikame eder ExpressionAttributeNames aracılığıyla — bir attribute bir rezerve kelimeyle çakıştığında veya bir nokta/boşluk içerdiğinde kullan.
  • :value bir değeri ikame eder ExpressionAttributeValues aracı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, bir ValidationException'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:

AttributeRezerve mi?Ne tutar
statusevetdraft / published
nameevetyazar görünen adı
sizeevetrender edilmiş byte uzunluğu
ttlevetarşiv sona erme (epoch)
slughayırURL 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ğibir attribute adıbir attribute değeri
EşlemeExpressionAttributeNamesExpressionAttributeValues
Önek#:
Gereken durumrezerve kelimeler, noktalar, boşluklarher zaman — satır içi literal yok
Yanlış olan hata verirValidationExceptionValidationException

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.

Güncellendi