DynamoDB Expressões de condição chave
Uma expressão de condição chave é o KeyConditionExpression que você passa para um
Query — a única parte da solicitação que DynamoDB usa para encontrar itens. Tudo
else (filtros, projeções) é executado depois que a leitura já foi medida.
O que é uma expressão de condição chave em DynamoDB?
Uma expressão de condição chave é KeyConditionExpression em um Query que informa a DynamoDB quais itens ler. Odeve ser uma igualdade (PK = :v); oleva um operador de intervalo - =, <, <=, >, >=, BETWEEN ou begins_with. Ele decide o que é lido e cobrado, diferentemente de um filtro.
- Odeve ser uma igualdade.
PK = :ve nada mais - não intervalos, sembegins_with, semIN. DynamoDB faz hash para localizar uma partição. - Ousa um operador de intervalo.
=,<,<=,>,>=,BETWEEN, oubegins_with— é aqui que você corta um. - Não é um filtro. Uma condição chave decide o que será lido e cobrado; um
FilterExpressionapenas corta o resultado depois que você paga pela leitura. - As chaves de classificação são ordenadas por bytes. Os operadores de intervalo são comparados lexicograficamente, portanto como você formata a string da chave de classificação é o seu poder de consulta.
Por que a chave de partição está bloqueada para igualdade
DynamoDB armazena itens fazendo hash da chave de partição para uma partição física. Um hash fornece um local, não um intervalo - portanto, não há nada para verificar através.
É por isso que PK > :v ou begins_with(PK, :v) são rejeitados completamente. O motor
não é possível responder "todas as partições cuja chave começa com X" sem ler o todo
table, que é exatamente o Scan que foi criado para evitar.
Vindo de SQL, parece ao contrário: WHERE id LIKE 'order%' é trivial em
Postgres. Em DynamoDB a chave de partição é um endereço, não uma coluna pesquisável.
A chave de classificação é onde mora o poder
Dentro de uma partição, os itens são armazenados classificados pela chave de classificação. Essa ordem é o que os operadores de alcance exploram - DynamoDB busca uma posição e lê adiante.
| Operador | Lê | Use-o para |
|---|---|---|
SK = :v | Um item exato | Um filho específico por sua chave |
SK < / <= / > / >= :v | Uma fatia aberta | "Tudo depois deste ponto" |
SK ENTRE :a E :b | Uma gama fechada (inclusiva) | Uma janela limitada — um intervalo de datas |
begins_with(SK, :p) | Uma fatia de prefixo | Um tipo ou hierarquia sob PK |
Não há LIKE, nem CONTAINS, nem ENDS_WITH na chave. Substring e
a correspondência de sufixos não é ordenada por bytes, portanto, forçaria uma leitura completa - por design,
o API não vai deixar você. A correspondência de substring existe via contains() em um
FilterExpression (onde você já pagou pela leitura); correspondência de sufixo
não está disponível no servidor - armazene uma chave invertida ou filtre-a
lado do cliente. (AWS: Expressões de condição chave)
Um exemplo prático: mensagens em um aplicativo de bate-papo
Digamos que você esteja criando um bate-papo baseado em canal. Uma tabela, particionada por canal, classificados por hora da mensagem. Esquema de chave original:
- Chave de partição
ChannelRef—CH#{channelId} - Chave de classificação
PostedAt— um carimbo de data/hora ISO-8601,MSG#2026-06-23T14:05:00Z
O prefixo MSG# mantém as linhas da mensagem classificáveis e distintas de qualquer outra linha
tipo que você pode colocar no mesmo canal (configuração fixada, associação).
Carregue as mensagens mais recentes de um canal. Apenas a chave de partição, as mais recentes primeiro:
KeyConditionExpression ChannelRef = :ch
ExpressionAttributeValues { ":ch": "CH#general" }
ScanIndexForward false
ScanIndexForward: false percorre a coleção classificada ao contrário - a maneira mais barata
para obter "o mais recente primeiro" sem classificar o lado do cliente.
Um dia específico com begins_with. Como o carimbo de data/hora é a chave de classificação e
é armazenado como texto, um prefixo de data é uma fatia limpa:
KeyConditionExpression ChannelRef = :ch AND begins_with(PostedAt, :day)
:ch "CH#general"
:day "MSG#2026-06-23"
Isso lê todas as mensagens em 23/06/2026 e nada mais - DynamoDB busca o prefixo e para quando cai no final. Isso só funciona porque o prefixo é uma verdadeira âncora esquerda de uma string ordenada por bytes.
Uma janela precisa com BETWEEN. Para "as mensagens durante as 14:00 horas",
um intervalo inclusivo supera um prefixo:
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 é inclusivo em ambos os limites, então escolha seus pontos finais deliberadamente - um
off-by-one aqui descarta ou duplica silenciosamente uma mensagem de borda.
Você pode montar e copiar qualquer uma dessas expressões, com o
Mapa ExpressionAttributeValues preenchido para você, no
DynamoDB construtor de expressões — útil para
acertando a sintaxe begins_with e BETWEEN na primeira vez.
Este construtor é predefinido para uma consulta pk =… AND begins_with(sk, …) — altere o
operador para ver a atualização KeyConditionExpression:
Veja no DynoTable
Execute a mesma condição chave em uma partição de canal real. No momento em que você definir
um filtro de chave de partição, DynoTable emite um Query — então você carrega apenas aquela fatia,
não toda a coleção.
A armadilha: confundir uma condição chave com um filtro
O erro caro é usar FilterExpression para fazer o trabalho de uma chave. Um
filter não pode nem fazer referência a PostedAt - é a chave de classificação e DynamoDB rejeita
um filtro em um atributo chave com uma ValidationException. Portanto, a solução alternativa é
duplique a data em um atributo simples e não-chave (MessageDate) e filtre
isso em vez disso:
KeyConditionExpression ChannelRef = :ch
FilterExpression begins_with(MessageDate, :day)
Isso parece equivalente à condição chave begins_with acima e retorna o
mesmas linhas - mas lê primeiro a partição inteira do canal e depois descarta
tudo fora do dia. Você é cobrado pela leitura completa.
Os filtros nunca reduzem o custo de leitura. Eles correm depois que DynamoDB mediu os itens,
a mesma arma que um Scan filtrado. Se um predicado
pode ir na condição chave, ele pertence a esse lugar.
Corrija-o a montante. Se um padrão de acesso não puder ser expresso como uma igualdade PK além de um intervalo de chaves de classificação, é um sinal de modelagem. Remodele a chave de classificação ou adicione um índice codificado para o padrão - consulte GSI vs LSI e design de tabela única para saber como organizar as chaves.
Armadilhas e próximos passos
- A chave de partição é sempre
=. Nunca há intervalos. Se você precisar de uma variedade de partições, você superou um únicoQuery. - Uma condição de chave de classificação por consulta. Você não pode
ANDdois predicados de chave de classificação; escolhaBETWEENoubegins_with, não ambos. - Palavras reservadas precisam de aliases. Uma chave chamada
TimestampouNamedeve usarExpressionAttributeNames(#ts) ou os erros de consulta. (AWS: palavras reservadas) BETWEENé inclusivo. Ambos os pontos de extremidade são correspondentes — projete seus limites consequentemente.
Elabore suas principais condições no construtor de expressão, então tente DynoTable para executá-los em suas próprias tabelas e ver exatamente qual fatia cada condição chave retorna.