Delen via


Gegevens toewijzen met behulp van gegevensstromen

Belangrijk

Deze pagina bevat instructies voor het beheren van Azure IoT Operations-onderdelen met behulp van Kubernetes-implementatiemanifesten, die in preview zijn. Deze functie is voorzien van verschillende beperkingen en mag niet worden gebruikt voor productieworkloads.

Raadpleeg de Aanvullende voorwaarden voor Microsoft Azure-previews voor juridische voorwaarden die van toepassing zijn op Azure-functies die in bèta of preview zijn of die anders nog niet algemeen beschikbaar zijn.

Gebruik de taal voor gegevensstroomtoewijzing om gegevens te transformeren in Azure IoT Operations. De syntaxis is een eenvoudige, maar krachtige manier om toewijzingen te definiëren waarmee gegevens van de ene indeling naar de andere worden getransformeerd. Dit artikel bevat een overzicht van de taal en de belangrijkste concepten van de toewijzing van gegevensstromen.

Met toewijzing kunt u gegevens van de ene indeling naar de andere transformeren. Houd rekening met de volgende invoerrecord:

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

Vergelijk deze met de uitvoerrecord:

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

In de uitvoerrecord worden de volgende wijzigingen aangebracht in de invoerrecordgegevens:

  • De naam van de velden is gewijzigd: het Birth Date veld is nu Date of Birth.
  • Opnieuw gestructureerde velden: beide Date of Birth Name zijn gegroepeerd onder de nieuwe Employee categorie.
  • Veld verwijderd: het Place of birth veld wordt verwijderd omdat het niet aanwezig is in de uitvoer.
  • Veld toegevoegd: Het Base Salary veld is een nieuw veld in de Employment categorie.
  • Veldwaarden zijn gewijzigd of samengevoegd: het Position veld in de uitvoer combineert de Position en Office velden uit de invoer.

De transformaties worden bereikt via toewijzing, wat doorgaans betrekking heeft op:

  • Invoerdefinitie: de velden in de invoerrecords identificeren die worden gebruikt.
  • Uitvoerdefinitie: opgeven waar en hoe de invoervelden zijn geordend in de uitvoerrecords.
  • Conversie (optioneel): de invoervelden wijzigen zodat deze in de uitvoervelden passen. expression is vereist wanneer meerdere invoervelden worden gecombineerd tot één uitvoerveld.

De volgende toewijzing is een voorbeeld:

{
  inputs: [
    'BirthDate'
  ]
  output: 'Employee.DateOfBirth'
}
{
  inputs: [
    'Position'  // - - - - $1
    'Office'    // - - - - $2
  ]
  output: 'Employment.Position'
  expression: '$1 + ", " + $2'
}
{
  inputs: [
    '$context(position).BaseSalary'
  ]
  output: 'Employment.BaseSalary'
}

In het voorbeeld wordt het volgende toegewezen:

  • Een-op-een-toewijzing: BirthDate wordt direct toegewezen aan Employee.DateOfBirth zonder conversie.
  • Veel-op-een-toewijzing: combineert Position en Office in één Employment.Position veld. De conversieformule ($1 + ", " + $2) voegt deze velden samen in een opgemaakte tekenreeks.
  • Contextuele gegevens: BaseSalary wordt toegevoegd vanuit een contextuele gegevensset met de naam position.

Veldverwijzingen

Veldverwijzingen laten zien hoe u paden in de invoer en uitvoer opgeeft met behulp van punt notatie zoals Employee.DateOfBirth of toegang tot gegevens uit een contextuele gegevensset via $context(position).

Eigenschappen van MQTT- en Kafka-metagegevens

Wanneer u MQTT of Kafka als bron of doel gebruikt, hebt u toegang tot verschillende metagegevenseigenschappen in de toewijzingstaal. Deze eigenschappen kunnen worden toegewezen in de invoer of uitvoer.

Eigenschappen van metagegevens

  • Onderwerp: Werkt voor zowel MQTT als Kafka. Het bevat de tekenreeks waarin het bericht is gepubliceerd. Voorbeeld: $metadata.topic.
  • Gebruikerseigenschap: In MQTT verwijst dit naar de vrije sleutel/waardeparen die een MQTT-bericht kan bevatten. Als het MQTT-bericht bijvoorbeeld is gepubliceerd met een gebruikerseigenschap met de sleutel 'prioriteit' en de waarde 'hoog', bevat de $metadata.user_property.priority verwijzing de waarde 'hoog'. Gebruikerseigenschapssleutels kunnen willekeurige tekenreeksen zijn en vereisen mogelijk escape-tekens: $metadata.user_property."weird key" gebruikt de sleutel 'rare sleutel' (met een spatie).
  • Systeemeigenschap: Deze term wordt gebruikt voor elke eigenschap die geen gebruikerseigenschap is. Op dit moment wordt slechts één systeemeigenschap ondersteund: $metadata.system_property.content_type, waarmee de eigenschap van het inhoudstype van het MQTT-bericht wordt gelezen (indien ingesteld).
  • Header: Dit is het Kafka-equivalent van de MQTT-gebruikerseigenschap. Kafka kan elke binaire waarde voor een sleutel gebruiken, maar de gegevensstroom ondersteunt alleen UTF-8-tekenreekssleutels. Voorbeeld: $metadata.header.priority. Deze functionaliteit is vergelijkbaar met gebruikerseigenschappen.

Eigenschappen van metagegevens toewijzen

Invoertoewijzing

In het volgende voorbeeld wordt de eigenschap MQTT topic toegewezen aan het origin_topic veld in de uitvoer:

inputs: [
  '$metadata.topic'
]
output: 'origin_topic'

Als de gebruikerseigenschap priority aanwezig is in het MQTT-bericht, ziet u in het volgende voorbeeld hoe u deze kunt toewijzen aan een uitvoerveld:

inputs: [
  '$metadata.user_property.priority'
]
output: 'priority'
Uitvoertoewijzing

U kunt metagegevenseigenschappen ook toewijzen aan een uitvoerheader of gebruikerseigenschap. In het volgende voorbeeld wordt de MQTT topic toegewezen aan het origin_topic veld in de gebruikerseigenschap van de uitvoer:

inputs: [
  '$metadata.topic'
]
output: '$metadata.user_property.origin_topic'

Als de binnenkomende nettolading een priority veld bevat, ziet u in het volgende voorbeeld hoe u deze kunt toewijzen aan een MQTT-gebruikerseigenschap:

inputs: [
  'priority'
]
output: '$metadata.user_property.priority'

Hetzelfde voorbeeld voor Kafka:

inputs: [
  'priority'
]
output: '$metadata.header.priority'

Selectors voor contextuele gegevenssets

Met deze selectors kunnen toewijzingen extra gegevens uit externe databases integreren, die worden aangeduid als contextualisatiegegevenssets.

Recordfiltering

Het filteren van records omvat het instellen van voorwaarden om te selecteren welke records moeten worden verwerkt of verwijderd.

Punt notatie

Punt notatie wordt veel gebruikt in computerwetenschap om te verwijzen naar velden, zelfs recursief. In het programmeren bestaan veldnamen meestal uit letters en cijfers. Een standaard voorbeeld van een punt-notatie kan er als volgt uitzien:

inputs: [
  'Person.Address.Street.Number'
]

In een gegevensstroom kan een pad dat wordt beschreven door punt notatie tekenreeksen en enkele speciale tekens bevatten zonder escapen nodig te hebben:

inputs: [
  'Person.Date of Birth'
]

In andere gevallen is ontsnappen noodzakelijk:

inputs: [
  'Person."Tag.10".Value'
]

Het vorige voorbeeld bevat onder andere speciale tekens puntjes in de veldnaam. Zonder te ontsnappen zou de veldnaam fungeren als scheidingsteken in de punt notatie zelf.

Hoewel een gegevensstroom een pad parseert, worden er slechts twee tekens als speciaal behandeld:

  • Puntjes (.) fungeren als veldscheidingstekens.
  • Als enkele aanhalingstekens aan het begin of einde van een segment worden geplaatst, start u een escape-sectie waarin puntjes niet worden behandeld als veldscheidingstekens.

Alle andere tekens worden behandeld als onderdeel van de veldnaam. Deze flexibiliteit is handig in indelingen zoals JSON, waarbij veldnamen willekeurige tekenreeksen kunnen zijn.

In Bicep staan alle tekenreeksen tussen enkele aanhalingstekens ('). De voorbeelden over het juiste quoteren in YAML voor Kubernetes-gebruik zijn niet van toepassing.

Ontsnappen

De primaire functie van ontsnappen in een punt-noterend pad is om plaats te bieden aan het gebruik van puntjes die deel uitmaken van veldnamen in plaats van scheidingstekens:

inputs: [
  'Payload."Tag.10".Value'
]

In dit voorbeeld bestaat het pad uit drie segmenten: Payload, Tag.10en Value.

Regels ontsnappen in punt notatie

  • Ontsnap elk segment afzonderlijk: Als meerdere segmenten puntjes bevatten, moeten deze segmenten tussen dubbele aanhalingstekens worden geplaatst. Andere segmenten kunnen ook worden geciteerd, maar dit heeft geen invloed op de interpretatie van het pad:

    inputs: [
      'Payload."Tag.10".Measurements."Vibration.$12".Value'
    ]
    

  • Correct gebruik van dubbele aanhalingstekens: dubbele aanhalingstekens moeten een escaped segment openen en sluiten. Aanhalingstekens in het midden van het segment worden beschouwd als onderdeel van de veldnaam:

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

In dit voorbeeld worden twee velden gedefinieerd: Payload en He said: "Hello", and waved. Wanneer onder deze omstandigheden een punt wordt weergegeven, blijft deze fungeren als scheidingsteken:

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

In dit geval wordt het pad gesplitst in de segmenten PayloadHe said: "Noen It is done" (beginnend met een spatie).

Segmentatie-algoritme

  • Als het eerste teken van een segment een aanhalingsteken is, zoekt de parser naar het volgende aanhalingsteken. De tekenreeks tussen deze aanhalingstekens wordt beschouwd als één segment.
  • Als het segment niet begint met een aanhalingsteken, identificeert de parser segmenten door te zoeken naar de volgende punt of het einde van het pad.

Jokerteken

In veel scenario's lijkt de uitvoerrecord nauw op de invoerrecord, met slechts kleine wijzigingen die nodig zijn. Wanneer u records behandelt die talloze velden bevatten, kan het handmatig opgeven van toewijzingen voor elk veld tijdrovend worden. Jokertekens vereenvoudigen dit proces door gegeneraliseerde toewijzingen toe te staan die automatisch op meerdere velden kunnen worden toegepast.

Laten we eens kijken naar een basisscenario om inzicht te hebben in het gebruik van sterretjes in toewijzingen:

inputs: [
  '*'
]
output: '*'

Deze configuratie toont een basistoewijzing waarbij elk veld in de invoer rechtstreeks wordt toegewezen aan hetzelfde veld in de uitvoer zonder wijzigingen. Het sterretje (*) fungeert als een jokerteken dat overeenkomt met een veld in de invoerrecord.

Dit is de werking van het sterretje (*) in deze context:

  • Patroonkoppeling: het sterretje kan overeenkomen met één segment of meerdere segmenten van een pad. Het fungeert als tijdelijke aanduiding voor alle segmenten in het pad.
  • Overeenkomende velden: Tijdens het toewijzingsproces evalueert het algoritme elk veld in de invoerrecord op basis van het patroon dat is opgegeven in de inputs. Het sterretje in het vorige voorbeeld komt overeen met alle mogelijke paden, waarbij elk afzonderlijk veld in de invoer effectief wordt aangepast.
  • Vastgelegd segment: het gedeelte van het pad dat het sterretje overeenkomt, wordt aangeduid als het captured segment.
  • Uitvoertoewijzing: In de uitvoerconfiguratie wordt het captured segment sterretje geplaatst. Dit betekent dat de structuur van de invoer behouden blijft in de uitvoer, waarbij de captured segment tijdelijke aanduiding van het sterretje wordt ingevuld.

Een ander voorbeeld laat zien hoe jokertekens kunnen worden gebruikt om subsecties te vergelijken en ze samen te verplaatsen. In dit voorbeeld worden geneste structuren in een JSON-object effectief platgemaakt.

Oorspronkelijke JSON:

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

Toewijzingsconfiguratie die jokertekens gebruikt:

{
  inputs: [
    'ColorProperties.*'
  ]
  output: '*'
}
{
  inputs: [
    'TextureProperties.*'
  ]
  output: '*'
}

Resulterende JSON:

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

Plaatsing van jokertekens

Wanneer u een jokerteken plaatst, moet u de volgende regels volgen:

  • Eén sterretje per gegevensreferentie: er is slechts één sterretje (*) toegestaan binnen één gegevensreferentie.
  • Volledige segmentkoppeling: Het sterretje moet altijd overeenkomen met een heel segment van het pad. Het kan niet worden gebruikt om slechts een deel van een segment te vinden, zoals path1.partial*.path3.
  • Plaatsing: Het sterretje kan in verschillende delen van een gegevensreferentie worden weergegeven:
    • Aan het begin: *.path2.path3 - Hier komt het sterretje overeen met een segment dat tot path2.path3.
    • In het midden: path1.*.path3 - In deze configuratie komt het sterretje overeen met elk segment tussen path1 en path3.
    • Aan het einde: path1.path2.* - Het sterretje aan het einde komt overeen met een segment dat erna path1.path2volgt.
  • Het pad met het sterretje moet tussen enkele aanhalingstekens (') staan.

Jokertekens met meerdere invoer

Oorspronkelijke JSON:

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

Toewijzingsconfiguratie die jokertekens gebruikt:

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

Resulterende JSON:

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

Als u jokertekens met meerdere invoer gebruikt, moet het sterretje (*) consistent hetzelfde Captured Segment zijn voor elke invoer. Wanneer * bijvoorbeeld wordt vastgelegd Saturation in het patroon *.Max, verwacht het toewijzingsalgoritmen de overeenkomende Saturation.Min overeenkomst met het patroon *.Min. Hier wordt * vervangen door de Captured Segment eerste invoer, die de vergelijking voor volgende invoer leidt.

Bekijk dit gedetailleerde voorbeeld:

Oorspronkelijke JSON:

{
  "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
    }
  }
}

Initiële toewijzingsconfiguratie die jokertekens gebruikt:

inputs: [
  '*.Max'    // - $1
  '*.Min'    // - $2
  '*.Avg'    // - $3
  '*.Mean'   // - $4
]

Met deze eerste toewijzing wordt geprobeerd een matrix te maken (bijvoorbeeld voor Opacity: [0.88, 0.91, 0.89, 0.89]). Deze configuratie mislukt omdat:

  • Met de eerste invoer *.Max wordt een segment vastgelegd, zoals Saturation.
  • De toewijzing verwacht dat de volgende invoer aanwezig is op hetzelfde niveau:
    • Saturation.Max
    • Saturation.Min
    • Saturation.Avg
    • Saturation.Mean

Omdat Avg en Mean zijn genest Midbinnen, legt het sterretje in de eerste toewijzing deze paden niet correct vast.

Configuratie van toewijzing gecorrigeerd:

inputs: [
  '*.Max'        // - $1
  '*.Min'        // - $2
  '*.Mid.Avg'    // - $3
  '*.Mid.Mean'   // - $4
]

Met deze herziene toewijzing worden de benodigde velden nauwkeurig vastgelegd. Hiermee geeft u de paden op die het geneste Mid object moeten bevatten, wat ervoor zorgt dat de sterretjes effectief werken op verschillende niveaus van de JSON-structuur.

Tweede regel versus specialisatie

Wanneer u het vorige voorbeeld van jokertekens met meerdere invoer gebruikt, kunt u de volgende toewijzingen overwegen die twee afgeleide waarden genereren voor elke eigenschap:

{
  inputs: [
    '*.Max'   // - $1
    '*.Min'   // - $2
  ]
  output: 'ColorProperties.*.Avg'
  expression: '($1 + $2) / 2'
}
{
  inputs: [
    '*.Max'   // - $1
    '*.Min'   // - $2
  ]
  output: 'ColorProperties.*.Diff'
  expression: '$1 - $2'
}

Deze toewijzing is bedoeld voor het maken van twee afzonderlijke berekeningen (Avg en Diff) voor elke eigenschap onder ColorProperties. In dit voorbeeld ziet u het resultaat:

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

Hier fungeert de tweede toewijzingsdefinitie voor dezelfde invoer als een tweede regel voor toewijzing.

Overweeg nu een scenario waarin een specifiek veld een andere berekening nodig heeft:

{
  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 dit geval heeft het Opacity veld een unieke berekening. Twee opties voor het afhandelen van dit overlappende scenario zijn:

  • Neem beide toewijzingen op voor Opacity. Omdat de uitvoervelden in dit voorbeeld verschillen, zouden ze elkaar niet overschrijven.
  • Gebruik de specifiekere regel voor Opacity en verwijder de meer algemene regel.

Overweeg een speciaal geval voor dezelfde velden om de juiste actie te bepalen:

{
  inputs: [
    '*.Max'   // - $1
    '*.Min'   // - $2
  ]
  output: 'ColorProperties.*'
  expression: '($1 + $2) / 2'
}
{
  inputs: [
    'Opacity.Max'   // - $1
    'Opacity.Min'   // - $2
  ]
  output: ''
}

Een leeg output veld in de tweede definitie impliceert het niet schrijven van de velden in de uitvoerrecord (effectief verwijderen Opacity). Deze installatie is meer dan Specialization een Second Rule.

Oplossing van overlappende toewijzingen per gegevensstroom:

  • De evaluatie wordt uitgevoerd vanaf de bovenste regel in de toewijzingsdefinitie.
  • Als een nieuwe toewijzing wordt omgezet in dezelfde velden als een vorige regel, zijn de volgende voorwaarden van toepassing:
    • Een Rank wordt berekend voor elke opgeloste invoer op basis van het aantal segmenten dat door het jokerteken wordt vastgelegd. Als dit bijvoorbeeld het Captured Segments geval is Properties.Opacity, is de Rank 2. Als het maar Opacityis, is het Rank 1. Een toewijzing zonder jokertekens heeft een Rank van 0.
    • Als de Rank laatste regel gelijk is aan of hoger is dan de vorige regel, wordt deze door een gegevensstroom als een Second Rule.
    • Anders behandelt de gegevensstroom de configuratie als een Specialization.

De toewijzing die naar een Opacity.Min lege uitvoer leidtOpacity.Max, heeft bijvoorbeeld een Rank van 0. Omdat de tweede regel een lagere Rank waarde heeft dan de vorige regel, wordt deze beschouwd als specialisatie en wordt de vorige regel overschreven, waarmee een waarde voor Opacitywordt berekend.

Jokertekens in contextuele gegevenssets

Laten we nu eens kijken hoe contextuele gegevenssets kunnen worden gebruikt met jokertekens via een voorbeeld. Overweeg een gegevensset met de naam position die de volgende record bevat:

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

In een eerder voorbeeld hebben we een specifiek veld uit deze gegevensset gebruikt:

inputs: [
  '$context(position).BaseSalary'
]
output: 'Employment.BaseSalary'

Deze toewijzing kopieert rechtstreeks BaseSalary vanuit de contextgegevensset naar de Employment sectie van de uitvoerrecord. Als u het proces wilt automatiseren en alle velden uit de position gegevensset wilt opnemen in de Employment sectie, kunt u jokertekens gebruiken:

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

Met deze configuratie kan een dynamische toewijzing worden uitgevoerd waarbij elk veld in de position gegevensset wordt gekopieerd naar de Employment sectie van de uitvoerrecord:

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

Laatst bekende waarde

U kunt de laatst bekende waarde van een eigenschap bijhouden. Achtervoegsel van het invoerveld waarmee ? $last de laatst bekende waarde van het veld wordt vastgelegd. Wanneer een eigenschap een waarde in een volgende invoerpayload mist, wordt de laatst bekende waarde toegewezen aan de nettolading van de uitvoer.

Denk bijvoorbeeld aan de volgende toewijzing:

inputs: [
  'Temperature ? $last'
]
output: 'Thermostat.Temperature'

In dit voorbeeld wordt de laatst bekende waarde van Temperature bijgehouden. Als een volgende invoerpayload geen waarde bevat Temperature , wordt de laatst bekende waarde gebruikt in de uitvoer.