L'attribut Type dans DynamoDB
En SQL, la table d'une ligne est son type — une ligne dans documents est un
document. Une table unique DynamoDB mélange toutes les entités sous un même schéma,
si bien qu'un item ne porte aucune réponse intégrée à la question « qu'est-ce que
c'est ? ».
L'attribut Type remet cette réponse en place : une simple chaîne sur chaque item qui nomme l'entité qu'il représente.
Qu'est-ce que l'attribut Type dans DynamoDB ?
L'attribut Type est une simple chaîne que tu estampilles sur chaque item — par exemple EntityType: "Document" — nommant l'entité que cet item représente. Parce qu'une table unique mélange de nombreuses entités sous un même schéma, les items ne portent aucun type intégré. Le Type le rétablit, pour que ton code identifie les lignes, filtre un GSI sur une seule entité et survive aux migrations.
- Estampille un Type à chaque écriture. Un seul attribut —
EntityType: "Document"— sur chaque item, sans exception. Cela coûte quelques octets et te sauvera plus tard. - Il identifie les entités dans une partition mixte. Un
Queryrenvoie des espaces de travail, des documents et des commentaires ensemble ; le Type indique à ton code lequel est lequel sans analyser les préfixes de clé. - Il permet le filtrage par entité unique sur un . Projette le Type dans un index et tu peux restreindre un index surchargé à un seul type d'entité.
- C'est ta trappe de secours pour les migrations. Quand tu exportes pour re-modéliser ou déplacer une entité vers sa propre table, le Type est la colonne sur laquelle tu découpes.
Pourquoi une table mixte perd le type
La conception à table unique stocke chaque entité dans une
seule table derrière des clés génériques comme PK et SK. C'est tout l'intérêt — un
seul Query renvoie un parent et ses enfants ensemble. Mais cela signifie qu'une
partition est hétérogène.
Prenons une application SaaS de collaboration documentaire. Une partition d'espace de travail contient l'enregistrement de l'espace, ses documents et les commentaires sur ces documents :
| 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 rend les quatre items en une seule lecture facturée. Ton code
a maintenant une liste d'items bruts et aucun moyen fiable de dire lequel est un document
et lequel est un commentaire — sinon en faisant de la correspondance de chaîne sur le
SK, ce qui devient fragile dès que ton format de clé change.
Estampille le Type sur chaque item
La solution est un seul attribut à chaque écriture, nommant l'entité :
| PK | SK | EntityType | title |
|---|---|---|---|
| WS#acme | META | Workspace | — |
| WS#acme | DOC#a1#META | Document | Q3 Roadmap |
| WS#acme | DOC#a1#CMT#0007 | Comment | — |
Brancher sur item.EntityType === "Document" est un test d'égalité stable. Analyser
SK.startsWith("DOC#") && SK.includes("#CMT#") est une supposition qui casse dès que tu
fais évoluer la clé. Le Type découple ta logique de lecture de ton encodage de clé —
c'est le vrai gain.
Une seule lecture renvoie trois types d'entités ; l'attribut Type aiguille chaque item vers le bon gestionnaire sans toucher aux clés.
Filtre un GSI jusqu'à une seule entité
Le Type gagne sa place sur les index. Disons que tu ajoutes un GSI indexé sur
GSI1PK = WS#acme, GSI1SK = updatedAt pour lister « tout ce qui a récemment changé dans
cet espace de travail, du plus récent au plus ancien ». Un index surchargé ramasse à la
fois des documents et des commentaires — mais une interface de flux ne veut peut-être que
les documents.
Deux façons de le restreindre, et la différence, c'est de l'argent :
| Approche | Ce que ça coûte | Quand l'utiliser |
|---|---|---|
FilterExpression sur le Type | Lit tous les items correspondants, les facture tous, écarte les non-correspondants après lecture | Les entités mixtes sont rares dans le résultat ; rapide à livrer |
Index épars (GSI1PK écrit uniquement sur l'entité cible) | Seule l'entité voulue atterrit dans l'index | Une entité domine ; tu veux zéro gaspillage |
En on-demand dans us-east-1, une Query de GSI qui renvoie 100 items mixtes de
2 Ko chacun facture environ 100 RCU en cohérence à terme — et une
FilterExpression sur EntityType compte quand même chaque ligne avant d'écarter les
commentaires. Un index épars qui n'indexe jamais les commentaires ne facture que les
lignes de documents. Modélise les deux formes dans le
calculateur de tarifs.
Une FilterExpression s'exécute après la lecture des items et après la
consommation de la capacité — AWS est explicite : le filtrage ne réduit pas le coût de
lecture
(DynamoDB Developer Guide : FilterExpression).
Filtrer sur le Type est honnête, pas gratuit : tu paies pour les commentaires que tu jettes.
Pour restreindre le flux aux documents, la requête porte une condition sur l'attribut Type.
Assemble la FilterExpression, les noms et les valeurs avec le
générateur d'expressions DynamoDB — il émet le
placeholder #t = :doc pour que tu ne te trompes pas sur un mot réservé.
KeyConditionExpression GSI1PK = :ws
FilterExpression #t = :doc
ExpressionAttributeNames { "#t": "EntityType" }
ExpressionAttributeValues { ":ws": "WS#acme", ":doc": "Document" }
Tu veux que l'index ne porte que des documents et sauter complètement le filtre ? Écris
GSI1PK uniquement sur les items de type document — un .
Les items sans la clé du GSI ne se répliquent jamais dans l'index, si bien que la lecture
ne touche que les documents. L'attribut Type est ce qui indique à ton écriture quels items
sont éligibles.
Garde la valeur stable et au singulier
Choisis la valeur une bonne fois et traite-la comme un enum. Document, jamais parfois
Doc et parfois document — une valeur qui dérive est pire qu'aucune valeur, car tes
tests d'égalité passent sur une casse et manquent silencieusement l'autre.
Un seul Type par item. Si un item semble être deux entités, c'est en général un signe de mauvais modèle — cela devrait être deux items, chacun dans sa propre collection ou plage de clé de tri, et non une seule ligne portant deux casquettes.
Le gain à la migration
La raison d'estampiller le Type avant d'en avoir besoin : le re-modelage. Le chemin de re-modelage recommandé est export, transformation, réimport — et AWS documente l'export en masse vers S3 précisément pour ce genre de remise en forme hors ligne (Exporter DynamoDB vers S3).
Le jour venu, le Type est la colonne sur laquelle tu fais GROUP BY. Tu veux extraire les
commentaires dans leur propre table, ou renormaliser l'export en fichiers par entité pour un
entrepôt analytique ? Tu découpes le dump sur EntityType. Sans lui, tu retombes dans la
rétro-ingénierie des clés sur des millions de lignes.
Étapes suivantes
L'attribut Type est une assurance bon marché : identifier les entités dans une lecture mixte, filtrer un GSI surchargé et découper proprement lors d'un re-modelage. Estampille-le sur chaque écriture dès le premier jour — le rajouter après coup sur une table en production implique un remplissage complet.
À lire aussi : conception à table unique pour le pattern de
partition mixte qu'il sert, GSI vs LSI pour choisir la forme d'index
derrière un index épars, et
Query vs Scan pour comprendre pourquoi une FilterExpression ne
t'économise jamais de coût de lecture.
Construis le filtre sur le Type avec le générateur d'expressions DynamoDB, et essaie DynoTable pour parcourir une vraie table multi-entités et voir la colonne Type s'aligner sur chaque item.