Das Type-Attribut in DynamoDB
In SQL ist die Tabelle einer Zeile ihr Typ — eine Zeile in documents ist ein
Dokument. Eine DynamoDB-Single-Table mischt jede Entität unter einem Schema,
also trägt ein Item keine eingebaute Antwort auf die Frage „Was ist das?".
Das Type-Attribut liefert diese Antwort zurück: ein einfacher String auf jedem Item, der die Entität benennt, die es repräsentiert.
Was ist das Type-Attribut in DynamoDB?
Das Type-Attribut ist ein einfacher String, den du auf jedes Item prägst — wie EntityType: "Document" — der die Entität benennt, die dieses Item repräsentiert. Weil eine Single Table viele Entitäten unter einem Schema mischt, tragen Items keinen eingebauten Typ. Der Type liefert ihn zurück, damit dein Code Zeilen identifiziert, einen GSI auf eine Entität filtert und Migrationen übersteht.
- Präge bei jedem Schreibvorgang einen Type auf. Ein Attribut —
EntityType: "Document"— auf jedem Item, ohne Ausnahme. Es kostet ein paar Bytes und erspart dir später viel. - Es identifiziert Entitäten in einer gemischten Partition. Eine
Queryliefert Workspaces, Dokumente und Kommentare zusammen zurück; der Type sagt deinem Code, was was ist, ohne Key-Präfixe zu parsen. - Es ermöglicht Single-Entity-Filtering auf einem GSI. Projiziere den Type in einen Index und du kannst einen überladenen Index auf genau einen Entitätstyp einschränken.
- Es ist dein Notausgang für Migrationen. Wenn du für eine Neumodellierung exportierst oder eine Entität in ihre eigene Tabelle verschiebst, ist der Type die Spalte, an der du aufteilst.
Warum eine gemischte Tabelle den Typ verliert
Single-Table-Design speichert jede Entität in
einer Tabelle hinter generischen Keys wie PK und SK. Genau das ist der Sinn —
eine Query liefert einen Parent und seine Children zusammen zurück. Aber das
bedeutet, eine Partition ist heterogen.
Nimm eine SaaS-App für Dokumentenzusammenarbeit. Eine Workspace-Partition hält den Workspace-Datensatz, seine Dokumente und die Kommentare zu diesen Dokumenten:
| 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" gibt alle vier Items in einem abgerechneten Read zurück.
Jetzt hat dein Code eine Liste roher Items und keine verlässliche Möglichkeit zu
sagen, welches ein Dokument und welches ein Kommentar ist — abgesehen vom
String-Matching auf dem SK, was brüchig wird, sobald sich dein Key-Format
ändert.
Präge den Type auf jedes Item
Die Lösung ist ein Attribut bei jedem Schreibvorgang, das die Entität benennt:
| PK | SK | EntityType | title |
|---|---|---|---|
| WS#acme | META | Workspace | — |
| WS#acme | DOC#a1#META | Document | Q3 Roadmap |
| WS#acme | DOC#a1#CMT#0007 | Comment | — |
Eine Verzweigung über item.EntityType === "Document" ist ein stabiler
Gleichheitscheck. SK.startsWith("DOC#") && SK.includes("#CMT#") zu parsen ist
eine Vermutung, die bricht, sobald du den Key überarbeitest. Der Type entkoppelt
deine Read-Logik von deiner Key-Kodierung — das ist der eigentliche Gewinn.
Ein Read liefert drei Entitätstypen zurück; das Type-Attribut routet jedes Item zum richtigen Handler, ohne die Keys anzufassen.
Einen GSI auf eine Entität filtern
Der Type verdient sich seinen Platz bei Indizes. Sagen wir, du fügst einen GSI
mit GSI1PK = WS#acme, GSI1SK = updatedAt hinzu, um „alles kürzlich Geänderte
in diesem Workspace, neuestes zuerst" aufzulisten. Ein überladener Index zieht
Dokumente und Kommentare herein — aber eine Feed-UI will vielleicht nur
Dokumente.
Zwei Wege, ihn einzuschränken, und der Unterschied ist Geld:
| Ansatz | Was es kostet | Wann verwenden |
|---|---|---|
FilterExpression auf Type | Liest alle passenden Items, berechnet alle, verwirft Nicht-Treffer nach dem Read | Gemischte Entitäten sind im Ergebnis selten; schnell fertig |
Sparse Index (Type im GSI1PK) | Nur die gewünschte Entität landet überhaupt im Index | Eine Entität dominiert; du willst null Verschwendung |
Eine FilterExpression läuft nachdem Items gelesen wurden und nachdem
Kapazität verbraucht wurde — AWS sagt ausdrücklich, dass Filtern die Read-Kosten
nicht senkt
(DynamoDB Developer Guide: FilterExpression).
Auf Type zu filtern ist ehrlich, nicht kostenlos: Du zahlst für die Kommentare,
die du wegwirfst.
Um den Feed auf Dokumente einzuschränken, trägt die Query eine Bedingung auf dem
Type-Attribut. Stelle die FilterExpression, Names und Values mit dem
DynamoDB Expression Builder zusammen — er
gibt den Platzhalter #t = :doc aus, damit du dich nicht an einem reservierten
Wort vertippst.
KeyConditionExpression GSI1PK = :ws
FilterExpression #t = :doc
ExpressionAttributeNames { "#t": "EntityType" }
ExpressionAttributeValues { ":ws": "WS#acme", ":doc": "Document" }
Willst du, dass der Index nur Dokumente führt und den Filter ganz überspringt?
Schreibe GSI1PK nur auf Dokument-Items — ein Sparse Index. Items ohne den
GSI-Key replizieren nie in den Index, sodass der Read allein Dokumente berührt.
Das Type-Attribut ist das, was deinem Writer sagt, welche Items qualifizieren.
Halte den Wert stabil und singulär
Wähle den Wert einmal und behandle ihn als Enum. Document, nie mal Doc und
mal document — ein driftender Wert ist schlimmer als kein Wert, denn deine
Gleichheitschecks bestehen bei einer Schreibweise und verfehlen die andere still.
Ein Type pro Item. Wenn sich ein Item wie zwei Entitäten anfühlt, ist das meist ein Modellierungsgeruch — es sollten zwei Items sein, jedes in seiner eigenen Collection oder seinem eigenen Sort-Key-Bereich, nicht eine Zeile mit zwei Hüten.
Der Migrations-Payoff
Der Grund, den Type aufzuprägen, bevor du ihn brauchst: Neumodellierung. Der empfohlene Pfad zur Neumodellierung ist exportieren, transformieren, reimportieren — und AWS dokumentiert Bulk-Export nach S3 für genau diese Art von Offline-Umformung (DynamoDB nach S3 exportieren).
Wenn dieser Tag kommt, ist der Type die Spalte, nach der du GROUP BY
gruppierst. Willst du Kommentare in ihre eigene Tabelle heben oder den Export in
Entitäts-Dateien für ein Analytics-Warehouse renormalisieren? Du teilst den Dump
an EntityType auf. Ohne ihn bist du wieder beim Reverse-Engineering von Keys
über Millionen von Zeilen.
Nächste Schritte
Das Type-Attribut ist eine günstige Versicherung: Entitäten in einem gemischten Read identifizieren, einen überladenen GSI filtern und sauber aufteilen, wenn du neu modellierst. Präge es vom ersten Tag an bei jedem Schreibvorgang auf — nachträglich auf eine Live-Tabelle aufzubringen bedeutet ein vollständiges Backfill.
Verwandte Lektüre: Single-Table-Design für das
Gemischte-Partition-Muster, dem dies dient, GSI vs LSI für
die Wahl der Index-Form hinter einem Sparse Index und
Query vs Scan dafür, warum eine FilterExpression dir
nie Read-Kosten spart.
Baue den Filter auf dem Type mit dem DynamoDB Expression Builder, und probiere DynoTable aus, um eine echte Tabelle mit gemischten Entitäten zu durchsuchen und zu sehen, wie sich die Type-Spalte über jedes Item ausrichtet.