Datendefinitionsmodell – Kernelemente
Datendefinitionsmodelle sind grundlegend für die Testdatengenerierungsfunktionen von DATAMIMIC. Dieses Dokument behandelt die wichtigsten Elemente – wenn Du neu bei DATAMIMIC bist, beginne hier. Für fortgeschrittene Funktionen siehe Fortgeschrittene Datendefinitionselemente.
Überblick
Datendefinitionsmodelle legen fest, wie Testdaten generiert, transformiert oder maskiert werden sollen. Die Kernelemente ermöglichen es Dir:
- Datengenerierungsaufgaben zu definieren
- Schlüsselfelder und deren Werte zu spezifizieren
- Variablen zu erstellen und zu verwenden
- Strukturierte Datensätze zu generieren
Ausdrucks-Syntax: {expr} vs {{ expr }}
DATAMIMIC unterstützt zwei Formen der Ausdruckssyntax mit unterschiedlichem Caching-Verhalten:
Syntax-Vergleich
| Syntax |
Verhalten |
Caching |
{expr} |
CACHED - Einmal pro Datensatziteration ausgewertet, dann gecacht |
Schneller bei wiederholten Referenzen |
{{ expr }} |
DYNAMISCH - Wird jedes Mal neu ausgewertet |
Frischer Wert bei jeder Referenz |
Verwende {expr} (gecacht) wenn:
- Das Ergebnis des Ausdrucks innerhalb eines Datensatzes konsistent sein soll
- Du denselben Ausdruck mehrfach referenzierst
- Performance bei komplexen Ausdrücken wichtig ist
Verwende {{ expr }} (dynamisch) wenn:
- Du jedes Mal frische Werte brauchst (z.B. Zeitstempel mit Präzision)
- Zufallswerte pro Verwendung eindeutig sein sollen
- Der Ausdruck Seiteneffekte hat
Beispiele
Zeitstempel-Verhalten
1
2
3
4
5
6
7
8
9
10
11
12
13 | <!-- Gecacht: Alle Zeitstempelfelder erhalten den GLEICHEN Wert innerhalb eines Datensatzes -->
<generate name="audit_log" count="100">
<key name="created_at" script="{now()}"/>
<key name="updated_at" script="{now()}"/> <!-- Gleich wie created_at -->
<key name="processed_at" script="{now()}"/> <!-- Gleich wie created_at -->
</generate>
<!-- Dynamisch: Jedes Zeitstempelfeld erhält einen FRISCHEN Wert -->
<generate name="event_stream" count="100">
<key name="event_time" script="{{now()}}"/>
<key name="log_time" script="{{now()}}"/> <!-- Unterschiedlich zu event_time -->
<key name="process_time" script="{{now()}}"/> <!-- Unterschiedlich zu log_time -->
</generate>
|
Zufallswert-Verhalten
| <!-- Gecacht: Gleicher Zufallswert bei mehrfacher Referenz -->
<generate name="data" count="100">
<key name="value1" script="{random.random()}"/>
<key name="value2" script="{random.random()}"/> <!-- Gleicher Ausdruck = gleicher gecachter Wert -->
</generate>
<!-- Dynamisch: Frischer Zufallswert jedes Mal -->
<generate name="data" count="100">
<key name="value1" script="{{random.random()}}"/>
<key name="value2" script="{{random.random()}}"/> <!-- Unterschiedlicher Wert -->
</generate>
|
Empfehlungstabelle
| Anwendungsfall |
Empfohlen |
Grund |
| Statische/deterministische Ausdrücke |
{expr} |
Bessere Performance |
| Zeitkritisch (Zeitstempel) |
{{ expr }} |
Wenn Präzision zwischen Feldern wichtig ist |
| Zufallswerte mit Eindeutigkeit |
{{ expr }} |
Frischer Wert bei jeder Auswertung |
| Komplexe Ausdrücke mit mehrfacher Referenz |
{expr} |
Konsistenz + Performance |
| Ausdrücke mit Seiteneffekten |
{{ expr }} |
Seiteneffekte werden ausgeführt |
Hinweis zu targetEntity
Für targetEntity in Single-File-Exportern verhalten sich {expr} und {{ expr }} identisch, weil der Ausdrucks-Cache für jeden Datensatz zurückgesetzt wird und der Wert einmal pro Datensatz ausgewertet wird. Siehe Dynamische targetEntity für Details.
Basiselemente
<setup>
Das <setup>-Element ist das Wurzelelement für alle Datengenerierungsaufgaben. Es enthält ein oder mehrere <generate>-Elemente, die spezifische Datengenerierungsoperationen definieren. Mehr zur Verwendung findest Du unter Konfigurationsmodelle.
| <setup>
<generate name="users" count="100">
<!-- Details zur Generierung kommen hier hin -->
</generate>
</setup>
|
<generate>
Das <generate>-Element ist das Herzstück der Datendefinitionsmodelle. Es definiert eine Datengenerierungsaufgabe und beinhaltet Attribute wie name, count und target. Mit diesem Element werden strukturierte Daten basierend auf den angegebenen Konfigurationen erstellt.
Attribute
- name: Gibt den Namen der Generierungsaufgabe an.
- count: Gibt die Anzahl der zu generierenden Datensätze an.
- source: Gibt die Datenquelle an (z.B.
data/active.ent.csv, mongo).
- target: Gibt das Ziel der Ausgabe an (z.B.
CSV, sqliteDB).
- type: Gibt den Typ der zu generierenden Daten an.
- cyclic: Aktiviert oder deaktiviert zyklische Generierung. Standard ist
False.
- selector: Gibt eine Datenbankabfrage für die Generierung an.
- separator: Gibt einen Trenner für die generierten Daten an. Standard ist
|.
- sourceScripted: Aktiviert oder deaktiviert die skriptgesteuerte Auswertung der Quelle in der Quelldatei (z.B.
example.ent.csv, example.json). Standard ist False.
- pageSize: Gibt die Seitengröße für die Datengenerierung an.
- storageId: Gibt die ID des Objektspeicher-Clients an (definiert durch
<object-storage>). Gilt für Datei-Exporter
(CSV/JSON/XML/Template) und ist nicht dasselbe wie targetClient.
- sourceUri: Gibt die URI der Datenquelle im Objektspeicher an (z.B.
datasource/employees.csv).
- exportUri: Gibt nur den Pfad/Prefix für den Export an (z.B.
export/). Der Dateiname kommt aus name
oder targetEntity, die Dateiendung aus dem jeweiligen Exporter.
- container: Gibt den Containernamen für Azure Blob Storage an.
- bucket: Gibt den Bucket-Namen für AWS S3 an.
- distribution: Gibt die Verteilung der Datenquelleniteration an (z.B.
random, ordered). Standard ist random.
- converter: Gibt einen Konverter zur Wertetransformation an.
- variablePrefix: Konfigurierbares Attribut, das das Präfix für Variablensubstitution in dynamischen Strings definiert (Standard ist __).
- variableSuffix: Konfigurierbares Attribut, das das Suffix für Variablensubstitution in dynamischen Strings definiert (Standard ist __).
- numProcess: Definiert die Anzahl der Prozesse für Multiprocessing, kann vom Elternelement
<setup> übernommen werden. Standard ist 1.
- mpPlatform: Definiert die Multiprocessing-Plattform. Zulässige Werte sind
multiprocessing und ray. Standardwert ist multiprocessing.
Übersicht (Ziel vs Speicher vs Quelle)
| Zweck |
Attribut(e) |
Hinweis |
| Exporter-Typ wählen |
target |
z.B. CSV, JSON, XML, Template, mongodb |
| DB/Kafka/Warehouse-Client wählen |
targetClient |
Nur für client-basierte Exporter, nicht für Objektspeicher |
| Objektspeicher-Client wählen |
storageId |
Referenziert <object-storage id="..."> |
| Export-Pfad/Prefix setzen |
exportUri |
Pfad/Prefix; Dateiname aus name/targetEntity, Endung aus Exporter |
| Aus Objektspeicher lesen |
source + sourceUri |
source = Client-ID, sourceUri = Objektpfad |
| Bucket/Container wählen |
bucket / container |
Optional; Standard aus Client-Konfiguration |
Kindelemente
<key>: Gibt Schlüsselfelder innerhalb der Datengenerierungsaufgabe an.
<variable>: Definiert Variablen, die bei der Datengenerierung verwendet werden.
<reference>: Definiert Referenzen auf andere generierte Daten.
<nestedKey>: Gibt verschachtelte Schlüsselfelder und deren Generierungsmethoden an.
<list>: Definiert Listen von Datenelementen.
<condition>: Definiert eine Bedingung, um Daten nur dann einzufügen, wenn diese erfüllt ist.
<array>: Definiert Arrays von Datenelementen.
<echo>: Gibt Text oder Variablen zur Protokollierung oder zum Debugging aus.
Beispiel 1: Verwendung von Objektspeicher für die Datengenerierung
| <setup>
<!-- Definiere object-storage mit ID, die auf die Umgebung verweist -->
<object-storage id="aws"/>
<!-- Schreibe Datei in den Objektspeicher (exportUri ist nur Pfad/Prefix) -->
<generate name="external_write" bucket="datamimic-01" storageId="aws" exportUri="/datamimic_exporting_result/" target="JSON, CSV, TXT, XML" count="100">
<key name="id" generator="IncrementGenerator"/>
<key name="name" type="string"/>
</generate>
<!-- Lese Datei aus dem Objektspeicher -->
<generate name="external_read" bucket="datamimic-01" sourceUri="datamimic_exporting_result/external_write.json" source="aws" />
</setup>
|
Objektspeicher lesen (source + sourceUri)
| <object-storage id="s3" />
<generate name="read_orders"
source="s3"
sourceUri="abc/test/myfile.csv"
bucket="my-bucket"
target="CSV"/>
|
Beispiel 2: Verwendung von selector mit einer Datenbank
| <generate name="CUSTOMER" source="mongodb" selector="find: 'CUSTOMER', filter: {'age': {'$lt': 30}}" >
<key name="id" generator="IncrementGenerator"/>
<key name="name" type="string"/>
</generate>
|
In diesem Beispiel:
- Der
selector wird verwendet, um die MongoDB-Datenbank abzufragen und alle Kunden unter 30 Jahren zu finden.
- Die Daten werden an den
ConsoleExporter ausgegeben.
Beispiel 3: Datengenerierung mit MongoDB und Aggregation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 | <setup >
<memstore id="mem"/>
<mongodb id="mongodb"/>
<!-- Lösche Sammlungen vor der Generierung neuer Daten -->
<generate name="delete_users" source="mongodb" selector="find: 'more_users', filter: {}" target="mongodb.delete"/>
<generate name="delete_orders" source="mongodb" selector="find: 'more_orders', filter: {}" target="mongodb.delete"/>
<generate name="delete_products" source="mongodb" selector="find: 'more_products', filter: {}" target="mongodb.delete"/>
<!-- Generiere Sammlungen für Bestellungen, Nutzer und Produkte -->
<generate name="more_orders" source="script/orders.json" target="mongodb"/>
<generate name="more_users" source="script/users.json" target="mongodb"/>
<generate name="more_products" source="script/products.json" target="mongodb"/>
<!-- Führe eine Aggregationsabfrage aus, um Nutzerbestellungen und Ausgaben zusammenzufassen -->
<generate name="more_summary" count="20" >
<variable name="result" source="mongodb"
selector='aggregate: "more_users",
pipeline: [
{
"$lookup": {
"from": "more_orders",
"localField": "user_id",
"foreignField": "user_id",
"as": "userOrders"
}
},
{
"$unwind": "$userOrders"
},
{
"$lookup": {
"from": "more_products",
"localField": "userOrders.order_item",
"foreignField": "product_name",
"as": "orderProducts"
}
},
{
"$unwind": "$orderProducts"
},
{
"$group": {
"_id": "$user_id",
"user_name": { "$first": "$user_name" },
"order_items": { "$push": "$userOrders.order_item" },
"quantities": { "$first": "$userOrders.quantity" },
"total_spending": {
"$sum": {
"$multiply": ["$userOrders.quantity", "$orderProducts.price"]
}
}
}
}
]'/>
<nestedKey name="users_orders" script="result"/>
</generate>
<!-- Lösche Sammlungen nach der Generierung -->
<generate name="delete_users" source="mongodb" selector="find: 'more_users', filter: {}" target="mongodb.delete"/>
<generate name="delete_orders" source="mongodb" selector="find: 'more_orders', filter: {}" target="mongodb.delete"/>
<generate name="delete_products" source="mongodb" selector="find: 'more_products', filter: {}" target="mongodb.delete"/>
</setup>
|
Beispiel 4: Datengenerierung mit Kafka
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | <setup >
<kafka-exporter id="kafkaLocal" environment="environment"/>
<kafka-importer id="kafka_importer" system="kafkaLocal" enable.auto.commit="True" auto.offset.reset="earliest" group.id="datamimic" decoding="UTF-8" environment="environment"/>
<!-- Setze Kafka-Topic zurück, indem alle Nachrichten konsumiert werden -->
<generate name="reset" source="kafka_importer" type="kafka" count="100" target=""/>
<!-- Generiere Daten für den Export nach Kafka und Konsole -->
<generate name="exported_data" count="10" target="ConsoleExporter, kafkaLocal">
<variable name="person" entity="Person"/>
<key name="name" script="person.name"/>
<key name="email" script="person.email"/>
</generate>
<!-- Importiere Daten aus Kafka -->
<generate name="imported_data" source="kafka_importer" type="kafka" count="20" distribution="ordered"/>
</setup>
|
Beispiel 5: Verwendung von Daten aus einer CSV-Datei
| <setup defaultSeparator="|">
<generate name="product1" source="data/products.ent.csv" separator="," distribution="ordered"/>
<generate name="product2" source="data/products_2.ent.csv" distribution="ordered"/>
</setup>
|
In diesem Beispiel:
- Zwei
generate-Aufgaben werden erstellt, die Daten aus CSV-Dateien beziehen und an den ConsoleExporter ausgeben.
Beispiel 6: Verwendung von cyclic mit Daten aus dem Speicher
1
2
3
4
5
6
7
8
9
10
11
12 | <setup >
<memstore id="mem"/>
<generate name="product" count="15" target="mem">
<key name="id" generator="IncrementGenerator"/>
<key name="name" values="'Alice', 'Bob', 'Cameron'"/>
</generate>
<!-- Generiere 30 nicht-zyklische und zyklische Produkte aus dem Speicher -->
<generate name="non-cyclic-product" type="product" count="30" cyclic="False" source="mem" target="" distribution="ordered"/>
<generate name="cyclic-product" type="product" count="30" cyclic="True" source="mem" target="" distribution="ordered"/>
<generate name="big-cyclic-product" type="product" count="100" cyclic="True" source="mem" target="" distribution="ordered"/>
</setup>
|
Beispiel 7: Verwendung von 'sourceScripted' mit JSON-Template
| <setup>
<generate name="json_data" source="script/data.json" sourceScripted="True" target="">
<variable name="random_age" generator="IntegerGenerator(min=18, max=65)"/>
<variable name="street_name" generator="StreetNameGenerator"/>
<variable name="address_number" generator="IntegerGenerator"/>
</generate>
</setup>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | [
{
"id": 1,
"name": "Alice",
"age": "{random_age}",
"address": "__address_number__, __street_name__ St"
},
{
"id": 2,
"name": "Bob",
"age": "{random_age}",
"address": "__address_number__, __street_name__ St"
},
{
"id": 3,
"name": "Cameron",
"age": "{random_age}",
"address": "__address_number__, __street_name__ St"
}
]
|
Ergebnis:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | [
{
"id": 1,
"name": "Alice",
"age": 23,
"address": "801538, Walnut Street St"
},
{
"id": 2,
"name": "Bob",
"age": 51,
"address": "680286, View Street St"
},
{
"id": 3,
"name": "Cameron",
"age": 29,
"address": "711086, Forest Street St"
}
]
|
In diesem Beispiel:
- Das Attribut
sourceScripted="True" wird verwendet, um das JSON-Template mit eingebetteten Variablen auszuwerten.
- Das JSON-Template enthält Platzhalter für Variablen wie
random_age, street_name und address_number.
- Wenn der gesamte JSON-Feldwert eine Variable ist, sollte sie in geschweifte Klammern
{} eingeschlossen werden (z.B. "age": "{random_age}"). Der zurückgegebene Wert kann ein String, Integer oder ein anderer Typ sein.
- Wenn eine Variable in einen String eingebettet ist, sollte sie in doppelte Unterstriche
__ eingeschlossen werden (z.B. "address": "__address_number__, __street_name__ St"). Der zurückgegebene Wert ist ein String. Du kannst das Präfix und Suffix für die Variablensubstitution auch mit den Attributen variablePrefix, variableSuffix, defaultVariablePrefix und defaultVariableSuffix anpassen. Zum Beispiel:
| <setup defaultVariablePrefix="-%" defaultVariableSuffix="%-">
<generate name="json_data" source="script/data.json" sourceScripted="True" target="">
<variable name="random_age" generator="IntegerGenerator(min=18, max=65)"/>
</generate>
</setup>
<setup>
<generate name="json_data" source="script/data.json" sourceScripted="True" target="" variablePrefix="-%" variableSuffix="%-">
<variable name="random_age" generator="IntegerGenerator(min=18, max=65)"/>
</generate>
</setup>
|
| <setup>
<generate name="json_data" count="1000000" mpPlatform="ray" target="">
<key name="random_age" generator="IntegerGenerator(min=18, max=65)"/>
<key name="street_name" generator="StreetNameGenerator"/>
<key name="address_number" generator="IntegerGenerator"/>
</generate>
</setup>
|
In diesem Beispiel:
- Generierungsaufgaben werden mit der Plattform ray statt mit dem Standard-Python-Multiprocessing ausgeführt.
Das <generate>-Element definiert eine Datengenerierungsaufgabe. Im einfachsten Fall benötigt es:
- name: Identifiziert die Generierungsaufgabe
- count: Gibt an, wie viele Datensätze generiert werden sollen
- target: (Optional) Gibt das Ausgabeformat an (z.B. CSV, JSON)
Einfaches Beispiel
| <setup>
<generate name="simple_users" count="10" target="CSV">
<key name="id" generator="IncrementGenerator"/>
<key name="name" type="string"/>
<key name="age" type="int"/>
</generate>
</setup>
|
Wesentliche Attribute
- name: Aufgabenbezeichner
- count: Anzahl der zu generierenden Datensätze
- target: Ausgabeformat (z.B.
CSV, JSON, ConsoleExporter)
- source: (Optional) Eingabedatenquelle
<key>
Das <key>-Element definiert Schlüsselfelder innerhalb einer Datengenerierungsaufgabe und legt deren Generierungsmethoden fest. Diese Felder sind entscheidend für die Erstellung eindeutiger Kennungen oder strukturierter Elemente in den generierten Daten. Das <key>-Element ermöglicht dynamische, konstante oder bedingte Datengenerierung und bietet verschiedene Attribute zur Anpassung des Verhaltens.
Attribute
- name: Gibt den Namen des Schlüssels an. Dies ist verpflichtend und wird als Feldname in den generierten Daten verwendet.
- type: Definiert den Datentyp des Schlüssels (z.B.
string, int, bool). Dies ist optional, wenn script oder generator verwendet wird.
- source: Gibt die Datenquelle für den Schlüssel an (z.B. eine Datenbank, eine Datei).
- separator: Gibt einen Trenner für CSV-Quellen an.
- values: Stellt eine Liste statischer Werte bereit, aus denen der Schlüssel ausgewählt werden kann.
- script: Definiert ein Skript zur dynamischen Generierung des Schlüsselwerts.
- generator: Gibt einen Generator zur automatischen Wertgenerierung an (z.B.
RandomNumberGenerator, IncrementGenerator).
- constant: Definiert einen konstanten Wert für den Schlüssel.
- condition: Gibt eine Bedingung an, die bestimmt, ob der Schlüssel generiert wird.
- converter: Gibt einen Konverter zur Wertetransformation an (z.B. Datumsumwandlung, Formatänderungen).
- pattern: Definiert ein Regex-Muster zur Validierung des Schlüsselwerts.
- inDateFormat / outDateFormat: Gibt Eingabe- und Ausgabeformate für Datumsumwandlungen an.
- defaultValue: Gibt einen Standardwert an, falls der Wert des Schlüssels null ist oder nicht generiert wird.
- nullQuota: Definiert die Wahrscheinlichkeit, dass der Schlüssel einen Nullwert erhält. Standard ist
0 (niemals null).
- database: Gibt die Datenbank an, die zur Wertgenerierung verwendet wird (z.B.
SequenceTableGenerator).
- string: Attribut zur Generierung komplexer Strings durch Einbetten von Variablen mit anpassbaren Trennzeichen (siehe Variablen-Abschnitt).
- variablePrefix: Konfigurierbares Attribut, das das Präfix für Variablensubstitution in dynamischen Strings definiert (Standard ist
__).
- variableSuffix: Konfigurierbares Attribut, das das Suffix für Variablensubstitution in dynamischen Strings definiert (Standard ist
__).
Beispiel 1: Generierung von konstanten und geskripteten Schlüsseln
| <setup>
<generate name="static_and_scripted_keys" count="5" >
<key name="static_key" constant="fixed_value"/>
<key name="dynamic_key" script="random.randint(1, 100)"/>
</generate>
</setup>
|
In diesem Beispiel:
static_key erhält für jeden Datensatz den konstanten Wert "fixed_value".
dynamic_key generiert für jeden Datensatz mit einem Skript eine Zufallszahl zwischen 1 und 100.
Beispiel 2: Umgang mit nullQuota für optionale Felder
| <setup>
<generate name="nullable_keys" count="10">
<key name="key_always_null" type="string" nullQuota="1"/> <!-- 100% Nullwerte -->
<key name="key_never_null" type="string" nullQuota="0"/> <!-- 0% Nullwerte -->
<key name="key_sometimes_null" type="string" nullQuota="0.5"/> <!-- 50% Nullwerte -->
</generate>
</setup>
|
In diesem Beispiel:
key_always_null hat immer einen Nullwert (nullQuota="1").
key_never_null hat nie einen Nullwert (nullQuota="0").
key_sometimes_null hat in 50% der Fälle einen Nullwert (nullQuota="0.5").
Beispiel 3: Verwendung von defaultValue als Fallback
| <setup>
<generate name="default_values" count="5">
<key name="key_with_empty_string" script="" defaultValue="default_value"/> <!-- Fallback auf default_value -->
<key name="key_with_none" script="None" defaultValue="default_value"/> <!-- Fallback auf default_value -->
<key name="key_with_condition" script="" defaultValue="default_value" condition="False"/> <!-- Bedingung False, keine Generierung -->
</generate>
</setup>
|
Hier:
- Die ersten beiden Schlüssel greifen auf ihren
defaultValue zurück, wenn das Skript einen leeren oder None-Wert erzeugt.
- Der dritte Schlüssel wird nicht generiert, da seine Bedingung
False ist.
Beispiel 4: Bedingte Schlüsselerzeugung
| <setup>
<generate name="conditional_keys" count="10">
<key name="conditional_key" script="random.randint(1, 100)" condition="random.randint(1, 100) > 50"/>
<key name="constant_key" constant="fixed_value" condition="True"/>
</generate>
</setup>
|
In diesem Beispiel:
conditional_key wird nur generiert, wenn eine Zufallszahl größer als 50 ist.
constant_key wird immer generiert, da die Bedingung True ist.
Beispiel 5: Verwendung von pattern zur Validierung
| <setup>
<generate name="pattern_matching" count="10">
<key name="email" script="'[email protected]'" pattern="^[\w\.-]+@[\w\.-]+\.\w+$"/>
<key name="phone_number" script="'123-456-7890'" pattern="^\d{3}-\d{3}-\d{4}$"/>
</generate>
</setup>
|
In diesem Beispiel:
- Der Wert des Schlüssels
email muss dem Regex-Muster für eine gültige E-Mail-Adresse entsprechen.
- Der Wert des Schlüssels
phone_number muss dem Regex-Muster für eine gültige Telefonnummer entsprechen (123-456-7890).
| <setup>
<generate name="date_format_conversion" count="10">
<key name="date_of_birth" script="'2023-10-12'" inDateFormat="%Y-%m-%d" outDateFormat="%d-%m-%Y"/>
</generate>
</setup>
|
In diesem Beispiel:
- Der Schlüssel
date_of_birth verwendet das Eingabeformat (inDateFormat="%Y-%m-%d"), um das Datum zu parsen, und wandelt es in das angegebene Ausgabeformat (outDateFormat="%d-%m-%Y") um.
Beispiel 7: Schlüsselerzeugung mit SequenceTableGenerator
| <setup>
<database id="sourceDB" system="postgres"/>
<generate name="sequence_key_generation" count="10" >
<key name="user_id" database="sourceDB" generator="SequenceTableGenerator"/>
</generate>
</setup>
|
Hier:
- Der Schlüssel
user_id wird mit einem SequenceTableGenerator aus einer PostgreSQL-Datenbank generiert.
- Dieser Generator stellt sicher, dass eindeutige, fortlaufende Werte aus der Datenbank gezogen werden.
Best Practices für die Verwendung von <key>
- Nutze
script für dynamische Werte: Verwende Skripte, um komplexe und dynamische Werte zu generieren, z.B. Zufallszahlen, Daten oder berechnete Werte.
- Setze
nullQuota für realistische Daten ein: Simuliere reale Szenarien, in denen manche Schlüssel Nullwerte haben.
- Fallback mit
defaultValue: Stelle sicher, dass Schlüssel immer einen Wert haben, falls ein Skript fehlschlägt oder None liefert.
- Musterabgleich zur Validierung: Nutze das Attribut
pattern, um bestimmte Formate zu erzwingen, z.B. E-Mail-Adressen oder Telefonnummern.
- Steuere die Schlüsselerzeugung mit
condition: Bestimme dynamisch, ob ein Schlüssel generiert werden soll, um komplexe Szenarien abzubilden.
<variable>
Das Element <variable> definiert Variablen, die in Datengenerierungs‑Tasks verwendet werden. Variablen können aus Datenbanken, Datensätzen (z.B. CSV/JSON) stammen oder dynamisch per Skript erzeugt werden. Sie schaffen Flexibilität, indem sie steuern, wie Daten bezogen oder iteriert werden. Neu in dieser Version ist das Attribut storage für explizite Steuerung bei voller Rückwärtskompatibilität.
Attribute
- name: Name der Variable.
- type: Datentyp der Variable (optional). Bei DB/File‑Quellen i.d.R. Tabellen‑/Collection‑/Entity‑Name.
- source: Datenquelle (z.B. eine Datenbank oder ein Dateipfad).
- selector: Abfrage, um Daten einmalig für die Variable aus einer Datenbank zu laden (wird einmal ausgeführt).
- iterationSelector: Abfrage, die in jeder Iteration ausgeführt wird, um dynamische Daten zu laden.
-
storage: Legt fest, wie die Variable Daten speichert/ausliefert. Optionen:
-
value – ein einzelner statischer Wert (Standard für Generatoren/Konstanten; bei Query: erste Zeile)
data – komplette Datenliste im Speicher (Random‑Access)
iterator – Cursor/Iterator über Zeilen; respektiert cyclic
- separator: Feldtrennzeichen (z.B. bei CSV‑Quellen).
- cyclic: Aktiviert/deaktiviert zyklische Iteration der Quelle (relevant für
storage="iterator").
- entity: Entity für die Datengenerierung (z.B. ein vordefiniertes Modell/Objekt).
- script: Skript zur dynamischen Erzeugung des Variablenwerts.
- weightColumn: Spalte zur gewichteten Auswahl (typisch bei CSV/DB‑Quellen).
- sourceScripted: Aktiviert die pro‑Zeile‑Template‑Auswertung für dateibasierte Quellen (CSV/JSON, gewichtete Quellen).
- generator: Generator für die Variable (z.B.
RandomNumberGenerator, IncrementGenerator).
- dataset: Datensatz für die Variable (meist ein Dateipfad).
- locale: Locale für die Datenerzeugung.
- inDateFormat / outDateFormat: Datumsformat‑Konvertierung Ein‑/Ausgabe.
- converter: Konverter zur Transformation des Variablenwerts.
- constant: Konstanter Festwert für die Variable.
- values: Liste möglicher Werte, aus denen ausgewählt wird.
- defaultValue: Standardwert, falls keine Daten verfügbar sind.
- pattern: Regex‑Muster zur Validierung des Inhalts.
- distribution: Steuerung der Auswahlverteilung (
random, ordered).
- database: Konkrete Datenbank für die Generierung (falls mehrere konfiguriert sind).
- string: Attribut für komplexe Strings mit eingebetteten Variablen via konfigurierbarer Delimiter (siehe Beispiele bei
<key>).
- variablePrefix / variableSuffix: Konfigurierbare Präfix/Suffix‑Delimiter für Variablensubstitution in dynamischen Strings (Standard
__). Global auf <setup> via defaultVariablePrefix / defaultVariableSuffix setzbar und pro Element überschreibbar.
Speichermodi
Verwende storage für ein explizites, vorhersagbares Verhalten:
value: einzelner statischer Wert. Ideal für Konfigurationswerte, skalare selector‑Abfragen, Konstanten, Generatoren.
data: vollständige Liste im Speicher. Nützlich für Analysen, Random‑Access oder Join‑Logik in Skripten. Speicherbedarf beachten.
iterator: effiziente Zeileniteration. Respektiert cyclic. Geeignet für große Tabellen/Dateien.
Automatisches Legacy‑Verhalten (rückwärtskompatibel)
Wenn storage weggelassen wird, wendet DataMimIC die bisherigen Regeln an:
- Selector‑Variablen → verhalten sich als statischer Einzelwert.
- Tabellen/Collection‑Variablen → iterieren zyklisch über Zeilen (Iterator‑Semantik).
- Generator/Konstante → Einzelwert.
Kontextebenen
- Root‑Variablen (direkt unter
<setup> deklariert): einmal geladen, im gesamten Lauf geteilt, stabil im Multiprocessing.
- Verschachtelte Variablen (innerhalb von
<generate>): pro Generierungskontext erzeugt; können bei cyclic="False" erschöpfen.
Hinweise zu Multiprocessing
storage="data": jeder Worker erhält die gleiche Snapshot‑Liste.
storage="iterator": jeder Worker bewegt seinen eigenen Cursor. Für globale, geteilte Traversierung lieber upstream partitionieren (z.B. per ID‑Ranges).
Beispiel 1: generator für fortlaufende Werte
| <setup>
<generate name="sequential_ids" count="10" >
<variable name="id" generator="IncrementGenerator"/>
<key name="generated_id" script="id"/>
</generate>
</setup>
|
In diesem Beispiel:
id nutzt den IncrementGenerator und erzeugt fortlaufende Zahlen.
- Die generierte ID wird je Datensatz auf
generated_id gemappt.
Beispiel 2: CSV‑Quelle mit separator
| <setup>
<generate name="person_data" count="5" >
<variable name="person" source="data/people.csv" separator="," distribution="ordered"/>
<key name="person_id" script="person.id"/>
<key name="person_name" script="person.name"/>
<key name="person_age" script="person.age"/>
</generate>
</setup>
|
In diesem Beispiel:
person wird aus einer CSV geladen; Felder sind durch Komma getrennt.
distribution="ordered" stellt die Quellreihenfolge sicher.
Beispiel 3: constant definieren
| <setup>
<generate name="constant_value_example" count="3" >
<variable name="country" constant="Germany"/>
<key name="user_country" script="country"/>
</generate>
</setup>
|
Hier:
country ist als Konstante "Germany" definiert und wird für alle Datensätze verwendet.
Beispiel 4: Dynamische Variablen per script
| <setup>
<generate name="dynamic_variables" count="5" >
<variable name="random_number" script="random.randint(1, 100)"/>
<variable name="full_name" script="fake.name()"/>
<key name="random_number_value" script="random_number"/>
<key name="full_name_value" script="full_name"/>
</generate>
</setup>
|
In diesem Beispiel:
random_number erzeugt eine Zufallszahl 1..100 per Skript.
full_name nutzt die fake‑Bibliothek für zufällige Namen.
Beispiel 5: cyclic mit CSV‑Quelle
| <setup>
<generate name="cyclic_people" count="8" >
<variable name="person" source="data/people.csv" cyclic="True" separator=","/>
<key name="person_id" script="person.id"/>
<key name="person_name" script="person.name"/>
</generate>
</setup>
|
In diesem Beispiel:
cyclic="True" sorgt dafür, dass nach dem Ende wieder von vorn begonnen wird.
Beispiel 6: distribution für zufällige Auswahl
| <setup>
<generate name="random_people" count="10" >
<variable name="person" source="data/people.csv" separator="," distribution="random"/>
<key name="person_id" script="person.id"/>
<key name="person_name" script="person.name"/>
</generate>
</setup>
|
Hier:
distribution="random" sorgt für zufällige Auswahl aus der CSV.
Beispiel 7: Iteration mit iterationSelector
| <setup>
<generate name="iterate_selector" count="20" >
<key name="iteration_count" generator="IncrementGenerator"/>
<variable name="user" source="dbPostgres"
iterationSelector="SELECT id, name FROM users WHERE id = __iteration_count__"/>
<key name="user_id" script="user[0].id"/>
<key name="user_name" script="user[0].name"/>
</generate>
</setup>
|
In diesem Beispiel:
iterationSelector wird pro Iteration mit dem aktuellen iteration_count ausgeführt und lädt dynamisch Benutzer‑Daten.
Beispiel 8: Gewichtete Auswahl mit weightColumn
| <setup>
<generate name="weighted_people" count="10" >
<variable name="people" source="data/people_weighted.csv" weightColumn="weight" separator=","/>
<key name="person_id" script="people.id"/>
<key name="person_name" script="people.name"/>
</generate>
</setup>
|
Hier:
weightColumn="weight" steuert die Auswahlhäufigkeit pro Zeile (höheres Gewicht ⇒ höhere Wahrscheinlichkeit).
Beispiel 9: Kombination mit verschachtelten Keys
1
2
3
4
5
6
7
8
9
10
11
12 | <setup>
<generate name="customer_info" count="10" >
<variable name="customer" source="data/customers.csv" cyclic="True"/>
<variable name="notification" source="data/notifications.csv" cyclic="True"/>
<key name="customer_id" script="customer.id"/>
<key name="customer_name" script="customer.name"/>
<nestedKey name="notifications" type="list" count="2">
<key name="notification_type" script="notification.type"/>
<key name="notification_message" script="notification.message"/>
</nestedKey>
</generate>
</setup>
|
In diesem Fall:
customer und notification kommen aus CSV‑Dateien.
nestedKey erzeugt pro Kunde zwei Benachrichtigungen.
Beispiel 10: Entities und lokalisierten Daten
| <setup>
<generate name="localized_data" count="5" >
<variable name="person" entity="Person" locale="de_DE"/>
<key name="person_name" script="person.full_name"/>
<key name="person_address" script="person.address"/>
</generate>
</setup>
|
In diesem Beispiel:
person wird über die Entity Person mit Locale de_DE generiert (z.B. Namen, Adressen).
Beispiel 11: string für dynamische/komplexe Strings
| <setup defaultVariablePrefix="%%" defaultVariableSuffix="%%">
<generate name="query_generation" count="1">
<variable name="collection" constant="'users'" />
<key name="query" string="find: %%collection%%, filter: {'status': 'active'}" />
</generate>
</setup>
|
In diesem Beispiel:
- Das
string‑Attribut erlaubt die dynamische Einbettung von collection in den String.
- Die benutzerdefinierten
%%‑Delimiter ersetzen den Standard __.
Beispiel 12: Standard‑variablePrefix/variableSuffix
| <setup>
<generate name="query_generation" count="1">
<variable name="collection" constant="'users'" />
<key name="query" string="find: __collection__, filter: {'status': 'active'}" />
</generate>
</setup>
|
Hier:
- Es werden die Standard‑Delimiter
__ für die Variablensubstitution verwendet.
Beispiel 13: Expliziter Iterator mit cyclic
| <setup>
<generate name="sales" count="50">
<variable name="products" source="db" type="product_table" storage="iterator" cyclic="True"/>
<key name="product_id" script="products.id"/>
</generate>
</setup>
|
Beispiel 14: Vollständigen Datensatz im Speicher halten
| <setup>
<variable name="all_users" source="db" type="user_table" storage="data"/>
<generate name="analytics" count="10">
<key name="total_users" script="len(all_users)"/>
<key name="random_user" script="all_users[random(0, len(all_users)-1)]"/>
</generate>
</setup>
|
Beispiel 15: Einzelwert‑Verhalten erzwingen
| <setup>
<generate name="test" count="5">
<variable name="first_user" source="db" type="user_table" storage="value"/>
<key name="template_user" script="first_user.name"/>
</generate>
</setup>
|
Bewährte Vorgehensweisen für <variable>
- Dynamische Datenerzeugung: Skripte für Zufallszahlen, Namen, Adressen etc. nutzen (
random, fake).
- Zyklisch vs. nicht‑zyklisch:
cyclic aktivieren, wenn Wiederholung gewünscht ist; sonst erschöpft die Quelle nach einem Durchlauf.
- Gewichtung & Randomisierung:
weightColumn für Bias, distribution="random" für Zufallsauswahl.
- Mit verschachtelten Keys kombinieren: Für strukturierte/hierarchische Ausgaben
nestedKey verwenden.
- Passenden
storage wählen: value für Skalare/Konfig, iterator für große Quellen, data für kleine Listen mit Indexzugriff.
- Explizites
type bei DB‑Quellen: Keine implizite Ableitung aus dem Variablennamen.
- Multiprocessing beachten:
data ist ein geteilter Snapshot; Iteratoren laufen pro Worker separat weiter.
Zusammenfassung der Speichermodi
| Variablenmuster |
Storage‑Modus |
Verhalten |
Use Case |
selector="..." |
auto → value |
Einzelwert |
Config, Max‑Werte, Konstanten |
type="table_name" |
auto → iterator |
Zyklische Iteration |
Beziehungen/Entitäten |
storage="value" |
explizit |
Einzelwert |
Statisches Verhalten erzwingen |
storage="data" |
explizit |
Komplette Liste |
Berechnungen, Random‑Access |
storage="iterator" |
explizit |
Zyklus/Erschöpfung per cyclic |
Kontrollierte Iteration |
<ml-train>
Das <ml-train>-Element wird verwendet, um Machine-Learning-Modelle mit Eingabedaten zu trainieren. Diese trainierten Modelle können dann als Quellen in <generate>-Elementen verwendet werden, um Originaldaten anzureichern.
Das <ml-train>-Element ist ein Kindelement von <setup>.
Attribute
- name: Gibt den Namen des Modells nach dem Training an. Dies ist verpflichtend und wird zur Referenzierung in anderen Elementen verwendet.
- source: Gibt die Datenquelle an (z.B. data/active.ent.csv, mongo).
- type: Gibt den Typ der zu generierenden Daten an.
- mode: Gibt den Trainingsmodus an. Aktuell gibt es 'default' und 'persist'. 'default' entfernt das Modell nach Abschluss aller Aufgaben, 'persist' behält das Modell bei.
- maxTrainingTime: Gibt die maximale Trainingszeit in Minuten an (z.B. 1, 5, 10).
- separator: Gibt den Trenner der Quelldatei an (z.B. ',' für CSV-Dateien).
Beispiel 1: Einfaches Modelltraining
| <setup>
<ml-train name="customer_csv_gen"
source="data/customer.ent.csv"
maxTrainingTime="1"
separator=","/>
<generate name="csv_customer" count="10000" pageSize="1000" source="customer_csv_gen" target="CSV">
<key name="id" generator="IncrementGenerator"/>
</generate>
</setup>
|
In diesem Beispiel:
- Das Modell "customer_csv_gen" wird mit Daten aus "data/customers.csv" trainiert.
- Der Modus ist nicht explizit angegeben, daher wird das Modell nach Abschluss entfernt.
- Die CSV-Datei verwendet Komma als Trenner.
- "generate" verwendet das trainierte Modell als Quelle zur Datengenerierung.
Beispiel 2: Training mit Persistenzmodus
1
2
3
4
5
6
7
8
9
10
11
12 | <setup numProcess="2">
<ml-train name="customer_csv_gen"
source="data/customer.ent.csv"
mode="persist"
maxTrainingTime="1"/>
<!-- Generiere synthetische CUSTOMER-Datensätze mit dem ML-Generator -->
<generate name="csv_customer" count="10000" pageSize="1000" source="customer_csv_gen" target="CSV">
<key name="id" generator="IncrementGenerator"/>
</generate>
</setup>
|
In diesem Beispiel:
- Der Modus ist auf "persist" gesetzt, das Modell bleibt nach Abschluss erhalten.
- Es kann später ohne erneutes Training verwendet werden.
| <setup numProcess="2">
<generate name="csv_customer" count="10000" pageSize="1000" source="customer_csv_gen" target="CSV">
<key name="id" generator="IncrementGenerator"/>
</generate>
</setup>
|
Für den Lifecycle Datenbankansicht -> ML-Generator-Ansicht und den projektbezogenen Wiederverwendungsfluss (inklusive source="ml://...") siehe ML-Generator aus Datenbank-Metadaten und ML-Generator-Ansicht.
Komplettes Basisbeispiel
Hier ein vollständiges Beispiel, das die Kernelemente kombiniert:
1
2
3
4
5
6
7
8
9
10
11
12
13 | <setup>
<generate name="user_data" count="100" target="CSV">
<!-- Definiere Variablen -->
<variable name="person" entity="Person"/>
<!-- Definiere Schlüssel -->
<key name="id" generator="IncrementGenerator"/>
<key name="first_name" script="person.given_name"/>
<key name="last_name" script="person.family_name"/>
<key name="age" type="int" generator="IntegerGenerator(min=18, max=80)"/>
<key name="status" constant="active"/>
</generate>
</setup>
|
Dies generiert 100 Benutzerdatensätze mit konsistenten, strukturierten Daten inklusive IDs, Namen, Alter und einem Statusfeld.
Nächste Schritte
Sobald Du mit diesen Kernelementen vertraut bist, schaue Dir die Fortgeschrittenen Datendefinitionselemente für komplexere Funktionen an, wie:
- Verschachtelte Datenstrukturen
- Bedingte Generierung
- Komplexe Datenmuster
- Arrays und Listen
- Erweiterte Variablenverwendung