O Atributo Type no DynamoDB
No SQL, a tabela de uma linha é o seu tipo — uma linha em documents é um
documento. Uma tabela única no DynamoDB mistura todas as entidades sob um mesmo
schema, então um item não carrega resposta nenhuma embutida para "o que é isto?".
O atributo Type devolve essa resposta: uma string simples em cada item nomeando a entidade que ele representa.
O que é o atributo Type no DynamoDB?
O atributo Type é uma string simples que você carimba em cada item — como EntityType: "Document" — nomeando a entidade que aquele item representa. Como uma tabela única mistura muitas entidades sob um mesmo schema, os itens não carregam tipo nenhum embutido. O Type devolve essa informação, para que seu código identifique registros, filtre uma GSI para uma única entidade e sobreviva a migrações.
- Carimbe um Type em toda escrita. Um atributo —
EntityType: "Document"— em cada item, sem exceções. Custa alguns bytes e te salva depois. - Ele identifica entidades em uma partição mista. Um
Queryretorna workspaces, documentos e comentários juntos; o Type diz ao seu código qual é qual sem analisar prefixos de chave. - Ele viabiliza a filtragem de uma única entidade em uma GSI. Projete o Type em um índice e você consegue restringir um índice sobrecarregado a exatamente um tipo de entidade.
- Ele é sua saída de emergência para migrações. Quando você exporta para remodelar ou move uma entidade para a própria tabela, o Type é a coluna pela qual você divide.
Por que uma tabela mista perde o tipo
O single-table design guarda toda entidade em uma
única tabela atrás de chaves genéricas como PK e SK. Esse é justamente o
ponto — um Query retorna um pai e seus filhos juntos. Mas isso significa que
uma partição é heterogênea.
Pegue um app SaaS de colaboração em documentos. Uma partição de workspace guarda o registro do workspace, seus documentos e os comentários nesses documentos:
| PK | SK | attributes |
|---|---|---|
| WS#acme | META | name, plan, seats |
| WS#acme | DOC#a1#META | title, owner, wordCount |
| WS#acme | DOC#a1#CMT#0007 | author, body, createdAt |
| WS#acme | DOC#a1#CMT#0008 | author, body, createdAt |
Query PK = "WS#acme" devolve os quatro itens em uma única leitura cobrada.
Agora seu código tem uma lista de itens crus e nenhuma forma confiável de dizer
qual é um documento e qual é um comentário — a não ser fazendo string-matching no
SK, o que é frágil no instante em que seu formato de chave muda.
Carimbe o Type em cada item
A correção é um atributo em toda escrita, nomeando a entidade:
| PK | SK | EntityType | title |
|---|---|---|---|
| WS#acme | META | Workspace | — |
| WS#acme | DOC#a1#META | Document | Q3 Roadmap |
| WS#acme | DOC#a1#CMT#0007 | Comment | — |
Ramificar com item.EntityType === "Document" é uma checagem de igualdade
estável. Analisar SK.startsWith("DOC#") && SK.includes("#CMT#") é um palpite que
quebra quando você muda a versão da chave. O Type desacopla sua lógica de leitura
da sua codificação de chave — esse é o ganho de verdade.
Uma leitura retorna três tipos de entidade; o atributo Type roteia cada item para o handler certo sem tocar nas chaves.
Filtre uma GSI para uma única entidade
O Type ganha o seu sustento nos índices. Digamos que você adicione uma GSI com
chave GSI1PK = WS#acme, GSI1SK = updatedAt para listar "tudo que mudou
recentemente neste workspace, do mais novo ao mais antigo". Um índice
sobrecarregado arrasta documentos e comentários — mas uma UI de feed pode querer
apenas documentos.
Duas formas de restringir, e a diferença é dinheiro:
| Abordagem | Quanto custa | Quando usar |
|---|---|---|
FilterExpression no Type | Lê todos os itens correspondentes, cobra por todos eles, descarta os não-match após a leitura | Entidades misturadas são raras no resultado; rápido de entregar |
Índice esparso (Type no GSI1PK) | Só a entidade que você quer chega ao índice | Uma entidade domina; você quer zero desperdício |
Um FilterExpression roda depois que os itens são lidos e depois que a
capacidade é consumida — a AWS é explícita de que filtrar não reduz o custo de
leitura
(DynamoDB Developer Guide: FilterExpression).
Filtrar pelo Type é honesto, não grátis: você paga pelos comentários que joga fora.
Para restringir o feed a documentos, a query carrega uma condição no atributo
Type. Monte o FilterExpression, os nomes e os valores com o
DynamoDB expression builder — ele emite o
placeholder #t = :doc para você não digitar errado uma palavra reservada.
KeyConditionExpression GSI1PK = :ws
FilterExpression #t = :doc
ExpressionAttributeNames { "#t": "EntityType" }
ExpressionAttributeValues { ":ws": "WS#acme", ":doc": "Document" }
Quer que o índice carregue apenas documentos e pule o filtro por completo?
Escreva GSI1PK somente nos itens de documento — um índice esparso. Itens sem
a chave da GSI nunca replicam para o índice, então a leitura toca apenas
documentos. O atributo Type é o que diz ao seu escritor quais itens se qualificam.
Mantenha o valor estável e singular
Escolha o valor uma vez e trate-o como um enum. Document, nunca às vezes Doc e
às vezes document — um valor que oscila é pior do que valor nenhum, porque suas
checagens de igualdade passam em uma capitalização e silenciosamente erram a outra.
Um Type por item. Se um item parece ser duas entidades, isso normalmente é um cheiro de modelagem — deveriam ser dois itens, cada um na própria coleção ou faixa de sort key, não uma linha vestindo dois chapéus.
O retorno da migração
A razão para carimbar o Type antes de precisar dele: a remodelagem. O caminho de remodelagem recomendado é exportar, transformar, reimportar — e a AWS documenta a exportação em massa para o S3 exatamente para esse tipo de reshaping offline (Exportando DynamoDB para S3).
Quando esse dia chegar, o Type é a coluna pela qual você faz GROUP BY. Quer
elevar comentários para a própria tabela, ou renormalizar a exportação em arquivos
por entidade para um data warehouse de analytics? Você divide o dump pelo
EntityType. Sem ele, você volta a fazer engenharia reversa de chaves em milhões
de linhas.
Próximos passos
O atributo Type é seguro barato: identifica entidades em uma leitura mista, filtra uma GSI sobrecarregada e divide de forma limpa quando você remodela. Carimbe-o em toda escrita desde o primeiro dia — retrofitá-lo em uma tabela viva significa um backfill completo.
Leitura relacionada: single-table design para o
padrão de partição mista que isto serve, GSI vs LSI para
escolher o formato de índice por trás de um índice esparso, e
Query vs Scan para entender por que um FilterExpression
nunca te economiza custo de leitura.
Monte o filtro no Type com o DynamoDB expression builder e experimente o DynoTable para navegar por uma tabela real de entidades mistas e ver a coluna Type se alinhar em cada item.