Teilen über


Zuordnen von Daten mithilfe von Dataflows

Wichtig

Die von Azure Arc unterstützte Vorschauversion von „Azure IoT Einsatz“ befindet sich derzeit in der Vorschauphase. Sie sollten diese Vorschausoftware nicht in Produktionsumgebungen verwenden.

Sie müssen eine neue Installation von „Azure IoT Einsatz“ bereitstellen, wenn ein allgemein verfügbares Release verfügbar wird. Sie werden kein Upgrade für eine Preview-Installation durchführen können.

Die zusätzlichen Nutzungsbestimmungen für Microsoft Azure-Vorschauen enthalten rechtliche Bedingungen. Sie gelten für diejenigen Azure-Features, die sich in der Beta- oder Vorschauversion befinden oder aber anderweitig noch nicht zur allgemeinen Verfügbarkeit freigegeben sind.

Verwenden Sie die Zuordnungssprache für Dataflows, um Daten in Azure IoT Einsatz zu transformieren. Bei der Syntax handelt es sich um eine einfache und dennoch leistungsfähige Methode zum Definieren von Zuordnungen, die Daten von einem Format in ein anderes transformieren. Dieser Artikel enthält eine Übersicht über die Zuordnungssprache für Dataflows und wichtige Konzepte.

Mit der Zuordnung können Sie Daten aus einem Format in ein anderes transformieren. Betrachten Sie den folgenden Eingabedatensatz:

{
  "Name": "Grace Owens",
  "Place of birth": "London, TX",
  "Birth Date": "19840202",
  "Start Date": "20180812",
  "Position": "Analyst",
  "Office": "Kent, WA"
}

Vergleichen Sie diesen mit dem Ausgabedatensatz:

{
  "Employee": {
    "Name": "Grace Owens",
    "Date of Birth": "19840202"
  },
  "Employment": {
    "Start Date": "20180812",
    "Position": "Analyst, Kent, WA",
    "Base Salary": 78000
  }
}

Im Ausgabedatensatz werden die folgenden Änderungen an den Eingabedaten vorgenommen:

  • Felder umbenannt: Das Feld Birth Date heißt jetzt Date of Birth.
  • Felder neu strukturiert: Sowohl Name als auch Date of Birth werden unter der neuen Kategorie Employee gruppiert.
  • Feld gelöscht: Das Feld Place of birth wurde entfernt, da es in der Ausgabe nicht vorhanden ist.
  • Feld hinzugefügt: Das Feld Base Salary ist ein neues Feld in der Kategorie Employment.
  • Feldwerte geändert oder zusammengeführt: Das Feld Position in der Ausgabe kombiniert die neuen Felder Position und Office aus der Eingabe.

Die Transformationen werden durch eine Zuordnung erreicht, die in der Regel Folgendes umfasst:

  • Eingabedefinition: Identifizieren der Felder in den verwendeten Eingabedatensätzen
  • Ausgabedefinition: Angeben, wo und wie die Eingabefelder in den Ausgabedatensätzen angeordnet sind
  • Konvertierung (optional): Ändern der Eingabefelder, damit diese in die Ausgabefelder passen. expression ist erforderlich, wenn mehrere Eingabefelder in einem einzelnen Ausgabefeld kombiniert werden.

Die folgende Zuordnung ist ein Beispiel:

- inputs:
  - BirthDate
  output: Employee.DateOfBirth

- inputs:
  - Position # - - - $1
  - Office # - - - - $2
  output: Employment.Position
  expression: $1 + ", " + $2

- inputs:
  - $context(position).BaseSalary
  output: Employment.BaseSalary

Im Beispiel wird Folgendes zugeordnet:

  • 1:1-Zuordnung: Dabei wird BirthDate ohne Konvertierung direkt Employee.DateOfBirth zugeordnet.
  • n:1-Zuordnung: Dabei werden Position und Office in einem einzigen Employment.Position-Feld kombiniert. Die Konvertierungsformel ($1 + ", " + $2) führt diese Felder in einer formatierten Zeichenfolge zusammen.
  • Kontextbezogene Daten: Dabei wird BaseSalary aus einem kontextbezogenen Dataset mit dem Namen position hinzugefügt.

Feldverweise

Feldverweise stellen mithilfe der Punktnotation wie Employee.DateOfBirth oder des Zugriffs auf Daten aus einem kontextbezogenen Dataset über $context(position) dar, wie Pfade in der Ein- und Ausgabe angegeben werden.

MQTT-Benutzereigenschaften

Wenn Sie MQTT als Quelle oder Ziel verwenden, können Sie auf MQTT-Benutzereigenschaften in der Zuordnungssprache zugreifen. Benutzereigenschaften können in der Eingabe oder in der Ausgabe zugeordnet werden.

Im folgenden Beispiel wird die MQTT-Eigenschaft topic dem Feld origin_topic in der Ausgabe zugeordnet.

    inputs:
       - $metadata.topic
    output: origin_topic

Sie können MQTT-Eigenschaften auch einem Ausgabeheader zuordnen. Im folgenden Beispiel wird die MQTT-Eigenschaft topic dem Feld origin_topic in der Benutzereigenschaft der Ausgabe zugeordnet:

    inputs:
       - $metadata.topic
    output: $metadata.user_property.origin_topic

Selektoren für Kontextualisierungsdatasets

Diese Selektoren ermöglichen Zuordnungen die Integration zusätzlicher Daten aus externen Datenbanken, die als Kontextualisierungsdatasets bezeichnet werden.

Datensatzfilterung

Zum Filtern von Datensätzen müssen Bedingungen festgelegt werden, um auszuwählen, welche Datensätze verarbeitet oder verworfen werden sollen.

Punktnotation

Die Punktnotation wird in der Informatik häufig verwendet, um auf Felder zu verweisen, auch rekursiv. Bei der Programmierung bestehen Feldnamen in der Regel aus Buchstaben und Zahlen. Das folgende Beispiel stellt eine Standardpunktnotation dar:

- inputs:
  - Person.Address.Street.Number

In einem Dataflow kann ein durch Punktnotation beschriebener Pfad Zeichenfolgen und einige Sonderzeichen enthalten, ohne dass Escapezeichen benötigt werden:

- inputs:
  - Person.Date of Birth

In anderen Fällen sind Escapezeichen erforderlich:

- inputs:
  - nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32

Das vorherige Beispiel enthält Sonderzeichen wie Punkte innerhalb des Feldnamens. Ohne Escapezeichen würde der Feldname als Trennzeichen in der Punktnotation selbst dienen.

Beim Parsen eines Pfads behandelt der Dataflow lediglich zwei Zeichen als Sonderzeichen:

  • Punkte (.) fungieren als Feldtrennzeichen.
  • Einzelne Anführungszeichen am Anfang oder Ende eines Segments beginnen eine Escapesequenz, in der Punkte nicht als Feldtrennzeichen behandelt werden.

Alle weiteren Zeichen werden als Teil des Feldnamens behandelt. Diese Flexibilität ist in Formaten wie JSON hilfreich, bei denen Feldnamen beliebige Zeichenfolgen sein können.

Die Pfaddefinition muss ebenfalls den YAML-Regeln entsprechen. Wenn ein Zeichen mit einer besonderen Bedeutung im Pfad enthalten ist, sind in der Konfiguration die korrekten Anführungszeichen erforderlich. In der YAML-Dokumentation werden genaue Regeln aufgeführt. Im folgenden Abschnitt werden einige Beispiele dargestellt, die die Notwendigkeit einer sorgfältigen Formatierung veranschaulichen:

- inputs:
  - ':Person:.:name:'   # ':' cannot be used as the first character without single quotation marks
  - '100 celsius.hot'   # numbers followed by text would not be interpreted as a string without single quotation marks

Escapezeichen

Die primäre Funktion von Escapezeichen in einem Pfad mit Punktnotation besteht darin, die Verwendung von Punkten als Teil von Feldnamen und nicht als Trennzeichen zu interpretieren:

- inputs:
  - 'Payload."Tag.10".Value'

Im vorherigen Beispiel besteht der Pfad aus drei Segmenten: Payload, Tag.10 und Value. Die äußeren einfachen Anführungszeichen (') sind aufgrund der YAML-Syntaxregeln erforderlich, wodurch doppelte Anführungszeichen innerhalb der Zeichenfolge verwendet werden können.

Regeln für Escapezeichen in der Punktnotation

  • Escapefunktion für einzelne Segmente: Wenn mehrere Segmente Punkte enthalten, müssen diese Segmente in doppelte Anführungszeichen eingeschlossen werden. Andere Segmente können ebenfalls in Anführungszeichen eingeschlossen werden, jedoch wirken sich diese nicht auf die Interpretation des Pfads aus:

    - inputs:
      - 'Payload."Tag.10".Measurements."Vibration.$12".Value'
    
  • Ordnungsgemäße Verwendung doppelter Anführungszeichen: Doppelte Anführungszeichen müssen ein Escapesegment öffnen und schließen. Anführungszeichen in der Mitte des Segments werden als Teil des Feldnamens betrachtet:

    - inputs:
      - 'Payload.He said: "Hello", and waved'
    

    In diesem Beispiel werden zwei Felder in dataDestination definiert: Payload und He said: "Hello", and waved. Wenn unter diesen Umständen ein Punkt angezeigt wird, fungiert er weiterhin als Trennzeichen:

    - inputs:
      - 'Payload.He said: "No. It is done"'
    

    In diesem Fall wird der Pfad beginnend mit einem Leerzeichen in die Segmente Payload, He said: "No und It is done" aufgeteilt.

Segmentierungsalgorithmus

  • Wenn das erste Zeichen eines Segments ein Anführungszeichen ist, sucht der Parser nach dem nächsten Anführungszeichen. Die zwischen diesen Anführungszeichen eingeschlossene Zeichenfolge wird als einzelnes Segment interpretiert.
  • Wenn das Segment nicht mit einem Anführungszeichen beginnt, identifiziert der Parser Segmente, indem er nach dem nächsten Punkt oder nach dem Ende des Pfads sucht.

Platzhalter

In vielen Szenarios ähnelt der Ausgabedatensatz dem Eingabedatensatz, wobei lediglich geringfügige Änderungen erforderlich sind. Bei Datensätzen mit zahlreichen Feldern kann die manuelle Angabe von Zuordnungen für jedes Feld mühsam sein. Mithilfe von Platzhaltern wird dieser Prozess vereinfacht, indem generalisierte Zuordnungen zugelassen werden, die automatisch auf mehrere Felder angewendet werden können.

Das folgende Beispiel enthält ein einfaches Szenario zur Veranschaulichung der Verwendung von Sternchen in Zuordnungen:

- inputs:
  - '*'
  output: '*'

Funktionsweise des Sternchens (*) in diesem Kontext:

  • Musterabgleich: Das Sternchen kann mit einem einzelnen Segment oder mit mehreren Segmenten eines Pfads übereinstimmen. Es fungiert als Platzhalter für alle Segmente im Pfad.
  • Feldabgleich: Während des Zuordnungsprozesses wertet der Algorithmus jedes Feld im Eingabedatensatz anhand des Musters aus, das in inputs angegeben ist. Das Sternchen im vorherigen Beispiel stimmt mit allen möglichen Pfaden überein und entspricht damit effektiv jedem einzelnen Feld in der Eingabe.
  • Erfasstes Segment: Der Teil des Pfads, dem das Sternchen entspricht, wird als captured segment bezeichnet.
  • Ausgabezuordnung: In der Ausgabekonfiguration wird captured segment an der Stelle platziert, an der das Sternchen angezeigt wird. Das bedeutet, dass die Struktur der Eingabe in der Ausgabe beibehalten wird, wobei captured segment den vom Sternchen bereitgestellten Platzhalter auffüllt.

Diese Konfiguration veranschaulicht die gewöhnlichste Form der Zuordnung, bei der jedes Feld in der Eingabe direkt einem entsprechenden Feld in der Ausgabe ohne Änderung zugeordnet wird.

In einem weiteren Beispiel wird veranschaulicht, wie mithilfe von Platzhaltern Unterabschnitte zugeordnet und zusammen verschoben werden können. Bei diesem Beispiel werden geschachtelte Strukturen in einem JSON-Objekt effektiv vereinfacht.

Ursprünglicher JSON-Code:

{
  "ColorProperties": {
    "Hue": "blue",
    "Saturation": "90%",
    "Brightness": "50%",
    "Opacity": "0.8"
  },
  "TextureProperties": {
    "type": "fabric",
    "SurfaceFeel": "soft",
    "SurfaceAppearance": "matte",
    "Pattern": "knitted"
  }
}

Zuordnungskonfiguration mit Platzhaltern:

- inputs:
  - 'ColorProperties.*'
  output: '*'

- inputs:
  - 'TextureProperties.*'
  output: '*'

Resultierender JSON-Code:

{
  "Hue": "blue",
  "Saturation": "90%",
  "Brightness": "50%",
  "Opacity": "0.8",
  "type": "fabric",
  "SurfaceFeel": "soft",
  "SurfaceAppearance": "matte",
  "Pattern": "knitted"
}

Platzhalterplatzierung

Wenn Sie einen Platzhalter platzieren, müssen Sie die folgenden Regeln einhalten:

  • Einzelnes Sternchen pro dataDestination: Lediglich ein Sternchen (*) ist innerhalb eines einzelnen Pfads zulässig.
  • Abgleich vollständiger Segmente: Das Sternchen muss immer mit einem ganzen Segment des Pfads übereinstimmen. Es kann nicht wie path1.partial*.path3 verwendet werden, um lediglich einen Teil eines Segments abzugleichen.
  • Positionierung: Das Sternchen kann in verschiedenen Teilen von dataDestination positioniert werden:
    • Am Anfang: *.path2.path3 – Das Sternchen entspricht jedem Segment bis path2.path3.
    • In der Mitte: path1.*.path3 – In dieser Konfiguration entspricht das Sternchen einem beliebigen Segment zwischen path1 und path3.
    • Am Ende: path1.path2.*– Das Sternchen am Ende entspricht einem beliebigen Segment nach path1.path2.
  • Der Pfad, der das Sternchen enthält, muss in einfache Anführungszeichen (') eingeschlossen werden.

Platzhalter mit mehreren Eingaben

Ursprünglicher JSON-Code:

{
  "Saturation": {
    "Max": 0.42,
    "Min": 0.67,
  },
  "Brightness": {
    "Max": 0.78,
    "Min": 0.93,
  },
  "Opacity": {
    "Max": 0.88,
    "Min": 0.91,
  }
}

Zuordnungskonfiguration mit Platzhaltern:

- inputs:
  - '*.Max'   # - $1
  - '*.Min'   # - $2
  output: 'ColorProperties.*'
  expression: ($1 + $2) / 2

Resultierender JSON-Code:

{
  "ColorProperties" : {
    "Saturation": 0.54,
    "Brightness": 0.85,
    "Opacity": 0.89 
  }    
}

Bei Verwendung von Platzhaltern mit mehreren Eingaben muss das Sternchen (*) für alle Eingaben konsistent dasselbe Captured Segment-Element darstellen. Beispiel: Wenn Saturation im Muster *.Max durch * erfasst wird, erwartet der Zuordnungsalgorithmus, dass das entsprechende Saturation.Min-Element mit Muster *.Minübereinstimmt. Hierbei wird * durch die Captured Segment aus der ersten Eingabe ersetzt, woran sich der Abgleich für nachfolgende Eingaben orientiert.

Betrachten Sie dieses detaillierte Beispiel:

Ursprünglicher JSON-Code:

{
  "Saturation": {
    "Max": 0.42,
    "Min": 0.67,
    "Mid": {
      "Avg": 0.51,
      "Mean": 0.56
    }
  },
  "Brightness": {
    "Max": 0.78,
    "Min": 0.93,
    "Mid": {
      "Avg": 0.81,
      "Mean": 0.82
    }
  },
  "Opacity": {
    "Max": 0.88,
    "Min": 0.91,
    "Mid": {
      "Avg": 0.89,
      "Mean": 0.89
    }
  }
}

Anfängliche Zuordnungskonfiguration mit Platzhaltern:

- inputs:
  - '*.Max'    # - $1
  - '*.Min'    # - $2
  - '*.Avg'    # - $3
  - '*.Mean'   # - $4
  output: 'ColorProperties.*'
  expression: ($1, $2, $3, $4)

Diese anfängliche Zuordnung versucht, ein Array zu erstellen (z. B. für Opacity: [0.88, 0.91, 0.89, 0.89]). Diese Konfiguration schlägt aus dem folgenden Grund fehl:

  • Die erste Eingabe *.Max erfasst ein Segment wie Saturation.
  • Die Zuordnung erwartet, dass die nachfolgenden Eingaben auf derselben Ebene vorhanden sind:
    • Saturation.Max
    • Saturation.Min
    • Saturation.Avg
    • Saturation.Mean

Da Avg und Mean in Mid geschachtelt sind, erfasst das Sternchen in der anfänglichen Zuordnung diese Pfade nicht korrekt.

Korrigierte Zuordnungskonfiguration:

- inputs:
  - '*.Max'        # - $1
  - '*.Min'        # - $2
  - '*.Mid.Avg'    # - $3
  - '*.Mid.Mean'   # - $4
  output: 'ColorProperties.*'
  expression: ($1, $2, $3, $4)

Diese überarbeitete Zuordnung erfasst die erforderlichen Felder korrekt. Die Pfade, die das geschachtelte Mid-Objekt enthalten sollen, werden korrekt angegeben, damit die Sternchen effektiv auf verschiedenen Ebenen der JSON-Struktur funktionieren.

Zweite Regel im Vergleich mit der Spezialisierung

Berücksichtigen Sie bei Verwendung des vorherigen Beispiels aus Platzhaltern mit mehreren Eingaben die folgenden Zuordnungen, die zwei abgeleitete Werte für jede Eigenschaft generieren:

- inputs:
  - '*.Max'   # - $1
  - '*.Min'   # - $2
  output: 'ColorProperties.*.Avg'
  expression: ($1 + $2) / 2

- inputs:
  - '*.Max'   # - $1
  - '*.Min'   # - $2
  output: 'ColorProperties.*.Diff'
  expression: abs($1 - $2)

Diese Zuordnung soll unter ColorProperties zwei separate Berechnungen (Avg und Diff) für jede Eigenschaft erstellen. Dieses Beispiel zeigt das Ergebnis:

{
  "ColorProperties": {
    "Saturation": {
      "Avg": 0.54,
      "Diff": 0.25
    },
    "Brightness": {
      "Avg": 0.85,
      "Diff": 0.15
    },
    "Opacity": {
      "Avg": 0.89,
      "Diff": 0.03
    }
  }
}

Hier fungiert die zweite Zuordnungsdefinition für dieselben Eingaben als zweite Regel für die Zuordnung.

Betrachten Sie nun ein Szenario, in dem ein bestimmtes Feld eine andere Berechnung benötigt:

- inputs:
  - '*.Max'   # - $1
  - '*.Min'   # - $2
  output: 'ColorProperties.*'
  expression: ($1 + $2) / 2

- inputs:
  - Opacity.Max   # - $1
  - Opacity.Min   # - $2
  output: ColorProperties.OpacityAdjusted
  expression: ($1 + $2 + 1.32) / 2  

In diesem Fall weist das Feld Opacity eine eindeutige Berechnung auf. Die folgenden zwei Optionen stehen für den Umgang mit diesem überlappenden Szenario zur Verfügung:

  • Schließen Sie beide Zuordnungen für Opacity ein. Da sich die Ausgabefelder in diesem Beispiel unterscheiden, würden sie sich gegenseitig nicht außer Kraft setzen.
  • Verwenden Sie die spezifischere Regel für Opacity, und entfernen Sie die generischere Regel.

Berücksichtigen Sie bei der Entscheidung für die korrekte Aktion einen Sonderfall für dieselben Felder:

- inputs:
  - '*.Max'   # - $1
  - '*.Min'   # - $2
  output: 'ColorProperties.*'
  expression: ($1 + $2) / 2

- inputs:
  - Opacity.Max
  - Opacity.Min
  output:   

Ein leeres output-Feld in der zweiten Definition impliziert nicht das Schreiben der Felder im Ausgabedatensatz, wodurch Opacity effektiv entfernt wird. Bei diesem Setup handelt es sich mehr um ein Specialization-Element als ein Second Rule-Element.

Auflösung überlappender Zuordnungen durch Dataflows:

  • Die Auswertung erfolgt von der obersten Regel in der Zuordnungsdefinition.
  • Wenn eine neue Zuordnung zu denselben Feldern wie eine vorherige Regel aufgelöst wird, gelten die folgenden Bedingungen:
    • Ein Rank-Element wird für jede aufgelöste Eingabe basierend auf der Anzahl der Segmente berechnet, die der Platzhalter erfasst. Wenn die Captured Segments-Elemente beispielsweise Properties.Opacity sind, lautet Rank 2. Wenn es nur Opacity ist, lautet Rank 1. Eine Zuordnung ohne Platzhalter weist Rank von 0 auf.
    • Wenn das Rank-Element der letzteren Regel gleich oder höher als die vorherige Regel ist, behandelt ein Dataflow es als Second Rule.
    • Andernfalls wird die Konfiguration vom Dataflow als Specialization behandelt.

Beispiel: Bei einer Zuordnung, die Opacity.Max und Opacity.Min zu einer leeren Ausgabe leitet, hat Rank den Wert 0. Da Rank in der zweiten Regel niedriger als bei der vorherigen Regel ist, gilt sie als Spezialisierung und setzt die vorherige Regel außer Kraft, die einen Wert für Opacity berechnen würde.

Platzhalter in Kontextualisierungsdatasets

Sehen wir uns nun in einem Beispiel an, wie Kontextualisierungsdatasets mi Platzhaltern verwendet werden können. Betrachten Sie das Dataset mit dem Namen position, das den folgenden Datensatz enthält:

{
  "Position": "Analyst",
  "BaseSalary": 70000,
  "WorkingHours": "Regular"
}

In einem früheren Beispiel wurde ein bestimmtes Feld aus diesem Dataset verwendet:

- inputs:
  - $context(position).BaseSalary
  output: Employment.BaseSalary

Bei dieser Zuordnung wird BaseSalary aus dem Kontextualisierungsdataset direkt in den Abschnitt Employment des Ausgabedatensatzes kopiert. Wenn Sie den Prozess automatisieren und alle Felder aus dem position-Dataset in den Abschnitt Employment einschließen möchten, können Sie Platzhalter verwenden:

- inputs:
  - '$context(position).*'
  output: 'Employment.*'

Diese Konfiguration ermöglicht eine dynamische Zuordnung, bei der jedes Feld innerhalb des position-Datasets in den Abschnitt Employment des Ausgabedatensatzes kopiert wird:

{
    "Employment": {      
      "Position": "Analyst",
      "BaseSalary": 70000,
      "WorkingHours": "Regular"
    }
}

Letzter bekannter Wert

Sie können den letzten bekannten Wert einer Eigenschaft nachverfolgen. Fügen Sie an das Eingabefeld das Suffix ? $last an, um den letzten bekannten Wert des Feldes zu erfassen. Wenn in einer nachfolgenden Eingabe-Payload ein Wert für eine Eigenschaft fehlt, wird der letzte bekannte Wert zur Ausgabe-Payload zugeordnet.

Betrachten Sie etwa die folgende Zuordnung:

- inputs:
  - Temperature ? $last
  output: Thermostat.Temperature

In diesem Beispiel wird der letzte bekannte Wert von Temperature nachverfolgt. Wenn eine nachfolgende Eingabe-Payload keinen Temperature-Wert enthält, wird der letzte bekannte Wert in der Ausgabe verwendet.