Paketkonfiguration
Die Konfiguration eines Pakets entscheidet, welche Artefakte Ihr Modell erzeugt. Kein Code – eine Deklaration. Diese Seite geht sie anhand der beiden Retail-Demo-Pakete durch, weil die dieselbe Geschäftswelt modellieren und völlig Verschiedenes daraus erzeugen.
Installieren Sie Demo: Retail Data Vault und generieren Sie: Sie bekommen dbt-Modelle für einen Data Vault. Installieren Sie Demo: Retail Business Objects und generieren Sie: Sie bekommen ein JSON-Schema je Objekt und einen HTML-Datenkatalog. Dieselben Kunden, dieselben Produkte, dieselben Bestellungen. Der Unterschied ist durchgehend Konfiguration.
Diese Seite erklärt die Hebel. Wenn Sie lieber daran ziehen und zusehen wollen, tut die Einführung genau das, eine Änderung nach der anderen.
Was ein Paket deklariert
Zwei Blöcke, und alles Weitere ist das eine oder das andere. Requirements sind das Vokabular, das das Paket in Ihrem Modell braucht; definitions sind die Regeln, die aus dem Modell Dateien machen.
{
"requirements": {
"entity_types": [
{ "name": "Business Object", "key": "ebo_object", "match_by": "key" },
{ "name": "Value Object", "key": "ebo_value_object", "match_by": "key" }
],
"attribute_types": [
{ "name": "Identifier", "key": "ebo_identifier", "match_by": "key" },
{ "name": "Required Property", "key": "ebo_required", "match_by": "key" },
{ "name": "Descriptive Property", "key": "ebo_descriptive", "match_by": "key" }
]
},
"definitions": [
{
"name": "ebo_object_schema",
"type_key": "ebo_object",
"template": "object.schema.json.jinja2",
"context_builder": "build_ebo_object_schema_context",
"name_pattern": "{name}.schema.json"
},
{
"name": "ebo_catalog",
"type_key": "model",
"scope": "model",
"template": "catalog.html.jinja2",
"context_builder": "build_ebo_catalog_context",
"name_pattern": "catalog.html"
}
]
}
Das ist die gesamte Konfiguration des Business-Object-Pakets, um die Beschreibungen gekürzt. Zwei Typen, drei Attributtypen, zwei Definitionen – und heraus kommen vier JSON-Schemata und ein Datenkatalog.
Die vier Hebel
1 · Der Entitätstyp entscheidet, ob eine Datei entsteht
Eine Definition nennt einen type_key und trifft auf Entitäten dieses Typs zu. Es gibt eine
Definition für ebo_object und keine für ebo_value_object – ein Value Object passt
also auf nichts und erzeugt nichts. Es hat keine eigene Identität, existiert nur innerhalb
des Objekts, das es enthält, und taucht nur dort eingebettet auf.
„Soll das eine Datei sein?" beantwortet der Typ, den Sie der Entität gegeben haben, und sonst nichts. Sie können das je Entität prüfen, ohne etwas zu generieren – siehe Show Templates.
match_by: "key" ist wichtig. Die Definition passt auf ebo_object, nicht auf den
Anzeigenamen „Business Object"; ein Umbenennen des Typs in Einstellungen → Typen macht
sie also nicht kaputt.
2 · Der Attributtyp gibt einer Spalte ihre Rolle
Der Datentyp eines Attributs sagt, was es ist: Text, Zahl, Datum. Der Attributtyp sagt, wofür es da ist, und das ist es, was die Vorlagen lesen.
Das Business-Object-Paket deklariert drei:
| Attributtyp | Im erzeugten Schema |
|---|---|
| Identifier | required und readOnly – der Geschäftsschlüssel |
| Required Property | required |
| Descriptive Property | optional |
So macht das Paket daraus Schema-Eigenschaften. Das ist der Code, der Ihr Modell liest, und es geht darin durchgehend um den Typ des Attributs:
for attr in self._attrs(entity_id):
role = self.imh.type_key(attr.id) if attr.type else None
if role not in (ROLE_IDENTIFIER, ROLE_REQUIRED, ROLE_DESCRIPTIVE):
continue # no type: skipped, not guessed at
json_type, json_format = JSON_TYPES.get(attr.datatype or "string", ("string", None))
out.append(PropertyContext(
name=attr.name,
json_type=json_type, # from the DATA type: date -> string/date
role=role,
required=role in (ROLE_IDENTIFIER, ROLE_REQUIRED),
read_only=role == ROLE_IDENTIFIER,
))
Zwei Fragen, an zwei Stellen beantwortet: attr.datatype sagt, was die Spalte ist,
type_key(attr.id) sagt, wofür sie da ist.
Ein Attribut ohne Typ wird übersprungen statt geraten. In einem API-Vertrag ist ein Feld, über dessen Verbindlichkeit niemand entschieden hat, schlimmer als ein fehlendes Feld.
Ein Attribut trägt auch ein mandatory-Kennzeichen, und es zu benutzen wäre einfacher
gewesen. Das Paket liest stattdessen den Attributtyp – zum einen, weil das sein Punkt ist,
zum anderen, weil ein Kennzeichen „Pflichtfeld" nicht von „Geschäftsschlüssel" unterscheiden
kann, und genau dieser Unterschied ist readOnly im Schema.
Das Data-Vault-Paket beantwortet dieselbe Frage mit anderen Typen – Hash Key, Business Key, Link Foreign Key, Hashdiff, Payload –, weil die Rolle einer Spalte in jener Welt eine andere Frage mit anderen Antworten ist.
3 · Der Beziehungstyp entscheidet über die Form
Beziehungen sind nicht nur Linien auf der Zeichenfläche; ein Paket liest sie.
Im Business-Object-Paket bettet Contains das Ziel in das Objekt ein, und References zeigt über dessen Identifier darauf. Dieselben zwei Objekte, mit einem anderen Beziehungstyp verbunden, erzeugen ein anderes Schema.
Im Data-Vault-Paket tragen die Beziehungen den Datenfluss – welcher Seed welche Staging-View speist, welche Staging-View welchen Hub – und die Hash-Spalten der Staging-View werden aus den Objekten berechnet, die sie speist. Modellieren Sie einen weiteren Hub, und diese Staging-View ändert sich, ohne dass jemand eine Vorlage bearbeitet.
4 · Benutzerdefinierte Eigenschaften tragen den Rest
Manches ist eine Aussage über ein Objekt und kein Feld davon: wem es gehört, wie es klassifiziert ist, welches System die führende Quelle ist. Das gehört in benutzerdefinierte Eigenschaften, und ein Paket kann die deklarieren, die es haben will.
Das Business-Object-Paket deklariert sechs – Geschäftsdomäne, Eigentümer, Data Steward, Klassifikation, Status, System of Record – und seine Katalogseite rendert sie als Tabelle. In keinem JSON-Schema tauchen sie auf, weil sie nicht Teil des Vertrags sind.

Ein Objekt ohne Eigentümer steht in diesem Katalog und wird oben darin genannt. Ein Katalog ist dazu da, das sichtbar zu machen, nicht es zu verbergen.
Die Vorlage
Eine Definition zeigt auf eine Vorlage, und die Vorlage macht aus dem Kontext eine Datei. Die Schema-Vorlage beginnt so:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": {@ ctx.title | tojson @},
"type": "object",
"properties": {
{=- for p in ctx.properties =}
{@ p.name | tojson @}: {
"type": {@ p.json_type | tojson @}{= if p.read_only =},
"readOnly": true{= endif =}
}{= if not loop.last =},{= endif =}
{=- endfor =}
}
}
Zwei Dinge zur Syntax, und beide haben schon Zeit gekostet:
Die Trennzeichen sind {@ … @} und {= … =}, nicht die üblichen doppelten Klammern. Das
ist Absicht: es lässt {{ … }} unangetastet, sodass eine Vorlage dbt- oder Jinja-Code in die
erzeugte Datei schreiben kann, ohne dass die Engine ihn auffrisst. Das Data-Vault-Paket
verlässt sich genau darauf.
Jeder Wert geht durch | tojson. JSON von Hand zusammenzusetzen bricht bei der ersten
Beschreibung mit einem Anführungszeichen – und es bricht beim Leser, nicht bei der
Generierung, die so oder so Erfolg meldete.
Ein Modell, zwei Arten von Ausgabe
Eine Definition deklariert auch ihren scope – wie oft sie läuft:
| Scope | Läuft | Erzeugt |
|---|---|---|
entity | einmal je passender Entität | eine Datei je Objekt |
model | einmal, für das ganze Modell | eine Datei über alles |
Das Business-Object-Paket nutzt beides. Seine Schema-Definition ist entity-scoped, vier Business Objects ergeben also vier Schema-Dateien. Seine Katalog-Definition ist model-scoped, das ganze Modell ergibt also genau eine HTML-Seite.
Beide Definitionen greifen gleichzeitig, auf dasselbe Modell, im selben Lauf. Jede Definition, deren Bedingungen passen, generiert – sie konkurrieren nicht und wissen nichts voneinander.
Wie eine Generierung aussieht
Führen Sie Generate All über das kombinierte Demo-Bundle aus, das beide Welten und beide Pakete trägt, und Sie bekommen zwölf Dateien aus einem Modell:
- sieben dbt-Modelle – drei Staging-Views, zwei Hubs, ein Link, ein Satellit;
- vier JSON-Schemata, eines je Business Object;
- eine HTML-Katalogseite.
Jedes Paket ignoriert stillschweigend die Entitäten des anderen. „Keine Vorlage für diesen Typ gefunden" ist die richtige Antwort, kein Fehlschlag.
Sehen, welche Regel gegriffen hat
Sie müssen kein Paket lesen, um herauszufinden, was es mit einer bestimmten Entität tut. Rechtsklick auf die Titelleiste des Objekts auf der Zeichenfläche, dann Show templates: der Reiter Templates listet jede passende Definition, das Artefakt, das sie erzeugen würde, und das Paket, aus dem sie stammt – und je Zeile meldet Explain why die passende Regel und View code zeigt die Datei, ohne etwas zu generieren.
Das einmal an Customer und einmal an Address der Demo zu tun, ist die kürzestmögliche Fassung dieser Seite. Ausführlich: Show Templates.
Die Demo-Pakete lesen
Beide Demo-Pakete sind offen – ihre Konfiguration ist lesbares JSON, und sie zu lesen ist der schnellste Weg zu sehen, wie die obigen Teile zusammenpassen. Jedes bringt eine README mit, die beschreibt, was es erzeugt, was es bewusst nicht erzeugt und welche seiner Aussagen ein Test abdeckt.
Der nächste Schritt von hier ist Eigene Assistenten: derselbe Gedanke, angewandt auf die Oberfläche der Anwendung, wo ein Assistent ebenfalls eine Deklaration ist.