Intermediário5 min de leitura

Nomes e valores de atributos de expressão DynamoDB

Expressões DynamoDB são modelos: você escreve espaços reservados e depois fornece o real Nomes e valores em dois mapas laterais. #name é um espaço reservado para nome; :value é um espaço reservado para valor. Confunda os dois e o DynamoDB rejeita o chamada inteira.

Qual é a diferença entre #name e :value no DynamoDB?

#name é um espaço reservado para um atributo nome, fornecido por meio de ExpressionAttributeNames; :value é um espaço reservado para um valor de atributo ****, fornecido por meio de ExpressionAttributeValues. Use #name para evitar palavras reservadas, pontos ou espaços, e :value para cada literal - DynamoDB nunca insere valores. Eles não são intercambiáveis; trocá-los lança um ValidationException.

  • #name substitui um nome de atributo via ExpressionAttributeNames — use sempre que um atributo entra em conflito com uma palavra reservada ou contém um dot/space.
  • :value substitui um valor via ExpressionAttributeValues — DynamoDB nunca insere literais no texto da expressão, portanto, cada valor é um espaço reservado.
  • Eles não são intercambiáveis. Um # ao qual um : pertence é um ValidationException, não um ambiente autônomo silencioso.

Vindo do SQL, você insere ambos – WHERE status = 'published'. Linhas DynamoDB nenhum dos dois. Essa divisão é o que confunde todo recém-chegado.

Por que os dois mapas existem

No SQL, a string de consulta carrega tudo: nomes de colunas, literais, operadores. DynamoDB separa deliberadamente a forma da expressão de seus dados.

Os valores vão em seu próprio mapa para que o DynamoDB possa digitar cada um (S, N, BOOL,…) e assim o analisador nunca precisa adivinhar onde termina uma string - não há aspas ou escapar para errar. Consulte tipos de dados no DynamoDB para a lista completa de tags de tipo.

Os nomes recebem o mesmo tratamento por um motivo diferente: DynamoDB tem uma longa lista de palavras reservadas, e qualquer atributo correspondente a uma delas não pode aparecer como um nome simples em uma expressão. O espaço reservado evita totalmente a reserva.

A armadilha da palavra reservada

Aqui está uma tabela de artigos CMS – chave de partição BLOG#<blog>, chave de classificação ARTICLE#<slug> – cujos atributos são lidos naturalmente, mas colidem com palavras reservadas:

AtributoReservado?O que contém
statussimdraft/published
namesimnome de exibição do autor
sizesimcomprimento de bytes renderizados
ttlsimexpiração do arquivo (época)
slugnãoLesma URL

status, name, size e ttl estão todos na lista de palavras reservadas do AWS, então este o filtro falha na primeira palavra:

FilterExpression  status = :s

DynamoDB retorna um ValidationException"O nome do atributo é reservado palavra-chave; palavra-chave reservada: status". A correção é um espaço reservado para nome, nunca renomeando o atributo:

FilterExpression           #status = :s
ExpressionAttributeNames   { "#status": "status" }
ExpressionAttributeValues  { ":s": { "S": "published" } }

slug não é reservado, então uma consulta que você testou em slug funciona e você supõe que a próxima também funcionará. Então o status quebra. A lista completa se move, então não memorize - coloque cada nome no lugar e você nunca será mordido.

Mapeie cada valor, sempre

Os valores não são negociáveis: não há sintaxe para um literal embutido. Mesmo uma planície número recebe um espaço reservado. Esta atualização marca um artigo publicado, carimba seu tamanho e define um arquivo de 30 dias:

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 :sz e :exp são enviados como strings N - o tipo de número do DynamoDB é wire- codificado como uma string. O mapa de valor também é onde você reutiliza um valor em cláusulas: defina :s uma vez, referencie-o em um ConditionExpression e em um FilterExpression.

Construir esses dois mapas manualmente é onde os erros de digitação se escondem. O Expression Builder gera a expressão string e ambos os mapas juntos, com as tags de tipo preenchidas, para que os espaços reservados não pode sair de sincronia.

O construtor abaixo filtra status – uma palavra reservada – para que você possa vê-la alias automático para #status no mapa ExpressionAttributeNames:

Monte sua requisição
Código gerado
new QueryCommand({
  "TableName": "AuditLog",
  "KeyConditionExpression": "#hashKey = :hashKeyValue",
  "FilterExpression": "#filter0 = :filterValue0",
  "ExpressionAttributeNames": {
    "#hashKey": "pk",
    "#filter0": "status"
  },
  "ExpressionAttributeValues": {
    ":hashKeyValue": {
      "S": "TENANT#acme"
    },
    ":filterValue0": {
      "S": "active"
    }
  }
})

Nomes para caminhos aninhados e estranhos

O espaço reservado # faz mais do que evitar palavras reservadas. A sintaxe do caminho do documento usa pontos e colchetes, portanto, um atributo que contém literalmente um ponto - digamos, um metadado chave og.title — não é endereçável sem um espaço reservado:

ProjectionExpression       #og
ExpressionAttributeNames   { "#og": "og.title" }

Sem ele, DynamoDB lê og.title como "o campo title dentro do mapa og"

  • uma coisa completamente diferente. A mesma história para nomes com espaços ou dígitos iniciais. Para aninhamento, coloque cada segmento como espaço reservado: #meta.#author com #meta e #author definido.

Nomes versus valores, lado a lado

#name:value
Substitutosum atributo nomeum atributo valor
MapaExpressionAttributeNamesExpressionAttributeValues
Prefixo#:
Necessário parapalavras reservadas, pontos, espaçossempre — sem literais embutidos
Erros erradosValidationExceptionValidationException

Se um valor fosse digitado como nome, o DynamoDB procuraria um atributo chamado published e sua condição nunca corresponderiam ao que você pretendia - então o API em vez disso, falha alto. Esse rigor é uma característica: não existe uma resposta silenciosamente errada.

Armadilhas e próximos passos

  • Declarando um espaço reservado que você não usa — DynamoDB rejeita entradas não utilizadas em qualquer mapa. Construa os mapas a partir da expressão, não à frente dela.
  • Reutilizando :v após editar a expressão — elimine uma cláusula e seu valor pode persistir, desencadeando o erro de entrada não utilizada. O construtor os mantém em sintonia.
  • Supondo que um nome é seguro porque funcionou uma vez — colisões de palavras reservadas são por atributo. Coloque o espaço reservado uniformemente e pare de adivinhar.

Esses mapas aparecem em todos os caminhos de gravação, então eles combinam naturalmente com design de mesa única e com conhecimento quando consultar versus verificar antes de anexar um filtro.

Gere a expressão mais ambos os mapas com o Construtor de Expressões, então experimente o DynoTable para executá-los em suas próprias mesas e observe o os espaços reservados são resolvidos.

Atualizado