Expression attribute name e value in DynamoDB
Le espressioni DynamoDB sono template: scrivi placeholder, poi fornisci i nomi di
attributo e i valori reali in due mappe a parte. #name è un placeholder di nome;
:value è un placeholder di valore. Confondi i due e DynamoDB rifiuta l'intera
chiamata.
Qual è la differenza tra #name e :value in DynamoDB?
#name è un placeholder per un nome di attributo, fornito tramite
ExpressionAttributeNames; :value è un placeholder per un valore di attributo,
fornito tramite ExpressionAttributeValues. Usa #name per schivare parole
riservate, punti o spazi, e :value per ogni literal — DynamoDB non incorpora mai
i valori. Non sono intercambiabili; scambiarli scatena una ValidationException.
#namesostituisce un nome di attributo tramiteExpressionAttributeNames— usalo ogni volta che un attributo si scontra con una parola riservata o contiene un punto/spazio.:valuesostituisce un valore tramiteExpressionAttributeValues— DynamoDB non incorpora mai i literal nel testo dell'espressione, quindi ogni valore è un placeholder.- Non sono intercambiabili. Un
#dove dovrebbe esserci un:è unaValidationException, non un no-op silenzioso.
Venendo da SQL, incorpori entrambi — WHERE status = 'published'. DynamoDB non
incorpora nessuno dei due. Quella separazione è ciò che fa inciampare ogni
neofita.
Perché esistono le due mappe
In SQL la stringa della query porta tutto: nomi di colonne, literal, operatori. DynamoDB separa deliberatamente la forma dell'espressione dai suoi dati.
I valori vanno nella loro mappa così che DynamoDB possa tipizzare ciascuno (S,
N, BOOL, …) e così che il parser non debba mai indovinare dove finisce una
stringa — non c'è quoting o escape da sbagliare. Vedi
i tipi di dati in DynamoDB per l'elenco completo dei
type-tag.
I nomi ricevono lo stesso trattamento per una ragione diversa: DynamoDB ha una lunga lista di parole riservate, e qualsiasi attributo che ne corrisponde una non può comparire come nome nudo in un'espressione. Il placeholder schiva del tutto la riserva.
La trappola delle parole riservate
Ecco una tabella di articoli CMS — partition key BLOG#<blog>, sort key
ARTICLE#<slug> — i cui attributi si leggono naturalmente ma si scontrano con
parole riservate:
| Attributo | Riservato? | Cosa contiene |
|---|---|---|
status | sì | draft / published |
name | sì | nome visualizzato autore |
size | sì | lunghezza in byte renderizzata |
ttl | sì | scadenza archivio (epoch) |
slug | no | slug URL |
status, name, size e ttl sono tutte nella lista delle parole riservate di
AWS, quindi questo filtro fallisce sulla prima parola:
FilterExpression status = :s
DynamoDB restituisce una ValidationException — "Attribute name is a reserved
keyword; reserved keyword: status". La soluzione è un name placeholder, mai
rinominare l'attributo:
FilterExpression #status = :s
ExpressionAttributeNames { "#status": "status" }
ExpressionAttributeValues { ":s": { "S": "published" } }
La trappola: slug non è riservata, quindi una query che hai testato contro
slug funziona, e dai per scontato che la prossima farà lo stesso. Poi status
la rompe. La lista completa si muove, quindi non memorizzarla — metti placeholder
su ogni nome e non ti morderà mai.
Mappa ogni valore, sempre
I valori sono irrinunciabili: non c'è sintassi per un literal inline. Anche un semplice numero ottiene un placeholder. Questo update segna un articolo come pubblicato, ne timbra la dimensione e imposta un TTL di archivio a 30 giorni:
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" }
}Nota che :sz e :exp sono inviati come stringhe N — il tipo number di
DynamoDB è codificato sul filo come stringa. La mappa dei valori è anche dove
riusi un valore tra clausole: definisci :s una volta, riferiscilo sia in una
ConditionExpression sia in una FilterExpression.
Costruire queste due mappe a mano è dove si nascondono i typo. L' Expression Builder genera la stringa dell'espressione ed entrambe le mappe insieme, con i type-tag riempiti, così i placeholder non possono andare fuori sincrono.
Nomi per percorsi annidati e scomodi
Il placeholder # fa di più che schivare le parole riservate. La sintassi
document-path usa punti e parentesi, quindi un attributo che contiene
letteralmente un punto — diciamo una chiave di metadati og.title — è
inindirizzabile senza un placeholder:
ProjectionExpression #og
ExpressionAttributeNames { "#og": "og.title" }
Senza di esso, DynamoDB legge og.title come "il campo title dentro la mappa
og" — una cosa del tutto diversa. Stessa storia per nomi con spazi o cifre
iniziali. Per l'annidamento, metti un placeholder su ogni segmento:
#meta.#author con sia #meta sia #author definiti.
Nomi vs valori, fianco a fianco
#name | :value | |
|---|---|---|
| Sostituisce | un nome di attributo | un valore di attributo |
| Mappa | ExpressionAttributeNames | ExpressionAttributeValues |
| Prefisso | # | : |
| Necessario per | parole riservate, punti, spazi | sempre — niente literal inline |
| Sbagliarne uno dà errore | ValidationException | ValidationException |
Se un valore fosse tipizzato come nome, DynamoDB cercherebbe un attributo chiamato
published e la tua condizione non corrisponderebbe mai come intendevi — quindi
l'API fallisce a voce alta. Quella rigidità è una funzionalità: non c'è risposta
silenziosamente sbagliata.
Trappole e prossimi passi
- Dichiarare un placeholder che non usi — DynamoDB rifiuta voci inutilizzate in entrambe le mappe. Costruisci le mappe dall'espressione, non prima di essa.
- Riusare
:vdopo aver modificato l'espressione — togli una clausola e il suo valore può restare, scatenando l'errore di voce inutilizzata. Il builder li tiene in lockstep. - Assumere che un nome sia sicuro perché ha funzionato una volta — gli scontri con le parole riservate sono per-attributo. Metti placeholder uniformemente e smetti di indovinare.
Queste mappe compaiono in ogni percorso di scrittura, quindi si abbinano naturalmente al single-table design e al sapere quando fare Query vs Scan prima ancora di attaccare un filtro.
Genera l'espressione più entrambe le mappe con l' Expression Builder, poi prova DynoTable per eseguirle contro le tue tabelle e guardare i placeholder risolversi.