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 nuDate of Birth
. - Opnieuw gestructureerde velden: beide
Date of Birth
Name
zijn gegroepeerd onder de nieuweEmployee
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 deEmployment
categorie. - Veldwaarden zijn gewijzigd of samengevoegd: het
Position
veld in de uitvoer combineert dePosition
enOffice
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 aanEmployee.DateOfBirth
zonder conversie. - Veel-op-een-toewijzing: combineert
Position
enOffice
in éénEmployment.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 naamposition
.
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.10
en 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 Payload
He said: "No
en 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 decaptured 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 totpath2.path3
. - In het midden:
path1.*.path3
- In deze configuratie komt het sterretje overeen met elk segment tussenpath1
enpath3
. - Aan het einde:
path1.path2.*
- Het sterretje aan het einde komt overeen met een segment dat ernapath1.path2
volgt.
- Aan het begin:
- 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, zoalsSaturation
. - 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 Mid
binnen, 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 hetCaptured Segments
geval isProperties.Opacity
, is deRank
2. Als het maarOpacity
is, is hetRank
1. Een toewijzing zonder jokertekens heeft eenRank
van 0. - Als de
Rank
laatste regel gelijk is aan of hoger is dan de vorige regel, wordt deze door een gegevensstroom als eenSecond Rule
. - Anders behandelt de gegevensstroom de configuratie als een
Specialization
.
- Een
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 Opacity
wordt 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.