El atributo Type en DynamoDB
En SQL, la tabla de una fila es su tipo — una fila en documents es un
documento. Una tabla única de DynamoDB mezcla cada entidad bajo un mismo esquema,
así que un item no lleva ninguna respuesta integrada a "¿qué es esto?".
El atributo Type devuelve esa respuesta: una simple cadena en cada item que nombra la entidad que representa.
¿Qué es el atributo Type en DynamoDB?
El atributo Type es una cadena simple que marcas en cada item — como EntityType: "Document" — que nombra la entidad que ese item representa. Dado que una tabla única mezcla muchas entidades bajo un mismo esquema, los items no llevan ningún tipo integrado. El Type lo devuelve, para que tu código identifique filas, filtre un GSI a una sola entidad y sobreviva a las migraciones.
- Marca un Type en cada escritura. Un atributo —
EntityType: "Document"— en cada item, sin excepciones. Cuesta unos pocos bytes y te salva más adelante. - Identifica entidades en una partición mixta. Una
Querydevuelve workspaces, documentos y comentarios juntos; el Type le dice a tu código cuál es cuál sin parsear prefijos de clave. - Habilita el filtrado por una sola entidad en un GSI. Proyecta el Type en un índice y podrás reducir un índice sobrecargado a exactamente un tipo de entidad.
- Es tu vía de escape para las migraciones. Cuando exportas para re-modelar o mover una entidad a su propia tabla, el Type es la columna por la que divides.
Por qué una tabla mixta pierde el tipo
El diseño de tabla única almacena cada entidad en una
tabla detrás de claves genéricas como PK y SK. De eso se trata — una sola
Query devuelve un padre y sus hijos juntos. Pero implica que una partición es
heterogénea.
Toma una app SaaS de colaboración en documentos. Una partición de workspace contiene el registro del workspace, sus documentos y los comentarios sobre esos 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" te devuelve los cuatro items en una sola lectura facturada.
Ahora tu código tiene una lista de items en bruto y ninguna forma fiable de decir
cuál es un documento y cuál un comentario — salvo emparejar cadenas sobre el SK,
lo cual es frágil en el momento en que cambias el formato de tu clave.
Marca el Type en cada item
La solución es un atributo en cada escritura, que nombre la entidad:
| PK | SK | EntityType | title |
|---|---|---|---|
| WS#acme | META | Workspace | — |
| WS#acme | DOC#a1#META | Document | Q3 Roadmap |
| WS#acme | DOC#a1#CMT#0007 | Comment | — |
Ramificar sobre item.EntityType === "Document" es una comprobación de igualdad
estable. Parsear SK.startsWith("DOC#") && SK.includes("#CMT#") es una conjetura
que se rompe cuando cambias la clave. El Type desacopla tu lógica de lectura de tu
codificación de claves — esa es la verdadera ventaja.
Una lectura devuelve tres tipos de entidad; el atributo Type enruta cada item al handler correcto sin tocar las claves.
Filtra un GSI hasta una sola entidad
El Type se gana su sitio en los índices. Digamos que añades un GSI con clave
GSI1PK = WS#acme, GSI1SK = updatedAt para listar "todo lo cambiado
recientemente en este workspace, primero lo más nuevo". Un índice sobrecargado
barre documentos y comentarios — pero una UI de feed puede querer solo
documentos.
Dos formas de reducirlo, y la diferencia es dinero:
| Enfoque | Lo que cuesta | Cuándo usarlo |
|---|---|---|
FilterExpression sobre Type | Lee todos los items que coinciden, factura todos, descarta los no coincidentes tras leer | Las entidades mixtas son raras en el resultado; rápido de implementar |
Índice disperso (Type en GSI1PK) | Solo la entidad que quieres llega al índice | Una entidad domina; quieres cero desperdicio |
Una FilterExpression se ejecuta después de leer los items y después de
consumir capacidad — AWS es explícito en que filtrar no reduce el coste de lectura
(DynamoDB Developer Guide: FilterExpression).
Filtrar por Type es honesto, no gratis: pagas por los comentarios que descartas.
Para reducir el feed a documentos, la query lleva una condición sobre el atributo
Type. Ensambla la FilterExpression, los nombres y los valores con el
constructor de expresiones de DynamoDB — emite el
placeholder #t = :doc para que no metas la pata con una palabra reservada.
KeyConditionExpression GSI1PK = :ws
FilterExpression #t = :doc
ExpressionAttributeNames { "#t": "EntityType" }
ExpressionAttributeValues { ":ws": "WS#acme", ":doc": "Document" }
¿Quieres que el índice lleve solo documentos y saltarte el filtro por completo?
Escribe GSI1PK únicamente en los items de documento — un índice disperso.
Los items sin la clave del GSI nunca se replican en el índice, así que la lectura
toca solo documentos. El atributo Type es lo que le dice a tu escritor qué items
califican.
Mantén el valor estable y singular
Elige el valor una vez y trátalo como un enum. Document, nunca a veces Doc y a
veces document — un valor que va a la deriva es peor que ningún valor, porque tus
comprobaciones de igualdad pasan con una capitalización y fallan en silencio con la
otra.
Un Type por item. Si un item parece dos entidades, eso suele ser un olor a mal modelado — deberían ser dos items, cada uno en su propia colección o rango de clave de ordenación, no una fila llevando dos sombreros.
La recompensa en la migración
La razón para marcar el Type antes de necesitarlo: el re-modelado. El camino de re-modelado recomendado es exportar, transformar, reimportar — y AWS documenta la exportación masiva a S3 exactamente para este tipo de reformado offline (Exportar DynamoDB a S3).
Cuando llegue ese día, el Type es la columna por la que haces GROUP BY. ¿Quieres
sacar los comentarios a su propia tabla, o renormalizar la exportación en archivos
por entidad para un almacén de analítica? Divides el volcado por EntityType. Sin
él, vuelves a hacer ingeniería inversa de claves a lo largo de millones de filas.
Próximos pasos
El atributo Type es un seguro barato: identifica entidades en una lectura mixta, filtra un GSI sobrecargado y divide de forma limpia cuando re-modelas. Márcalo en cada escritura desde el primer día — añadirlo a posteriori sobre una tabla viva significa un backfill completo.
Lectura relacionada: diseño de tabla única para el
patrón de partición mixta al que esto sirve, GSI vs LSI para
elegir la forma de índice detrás de un índice disperso, y
Query vs Scan para entender por qué una FilterExpression
nunca te ahorra coste de lectura.
Construye el filtro sobre el Type con el constructor de expresiones de DynamoDB, y prueba DynoTable para explorar una tabla real de entidades mixtas y ver la columna Type alinearse en cada item.