Сопоставление данных с помощью потоков данных
Внимание
Предварительная версия операций Интернета вещей Azure, включенная Azure Arc в настоящее время в предварительной версии. Не следует использовать это программное обеспечение предварительной версии в рабочих средах.
Вам потребуется развернуть новую установку Операций Интернета вещей Azure, когда общедоступная версия станет доступной. Вы не сможете обновить предварительную установку.
Юридические условия, применимые к функциям Azure, которые находятся в бета-версии, предварительной версии или в противном случае еще не выпущены в общедоступную версию, см . в дополнительных условиях использования для предварительных версий Microsoft Azure.
Используйте язык сопоставления потоков данных для преобразования данных в операциях Интернета вещей Azure. Синтаксис — это простой и мощный способ определения сопоставлений, которые преобразуют данные из одного формата в другой. В этой статье приведены общие сведения о языке сопоставления потоков данных и основных понятиях.
Сопоставление позволяет преобразовать данные из одного формата в другой. Рассмотрим следующую входную запись:
{
"Name": "Grace Owens",
"Place of birth": "London, TX",
"Birth Date": "19840202",
"Start Date": "20180812",
"Position": "Analyst",
"Office": "Kent, WA"
}
Сравните его с выходной записью:
{
"Employee": {
"Name": "Grace Owens",
"Date of Birth": "19840202"
},
"Employment": {
"Start Date": "20180812",
"Position": "Analyst, Kent, WA",
"Base Salary": 78000
}
}
В выходной записи в входные данные записей вносятся следующие изменения:
- Поля переименованы:
Birth Date
поле теперьDate of Birth
. - Поля реструктурированы: оба
Name
иDate of Birth
группируются под новойEmployee
категорией. - Удалено поле:
Place of birth
поле удаляется, так как оно отсутствует в выходных данных. - Добавлено поле:
Base Salary
поле является новым полемEmployment
в категории. - Значения полей изменились или объединены:
Position
поле в выходных данных объединяетPosition
поля изOffice
входных данных.
Преобразования выполняются путем сопоставления, которое обычно включает в себя:
- Определение входных данных: определение полей в входных записях, используемых.
- Определение выходных данных: указание того, где и как упорядочены поля ввода в выходных записях.
- Преобразование (необязательно): изменение входных полей для соответствия выходным полям.
expression
требуется, если несколько полей ввода объединяются в одно выходное поле.
Ниже приведен пример сопоставления.
{
inputs: [
'BirthDate'
]
output: 'Employee.DateOfBirth'
}
{
inputs: [
'Position' // - - - - $1
'Office' // - - - - $2
]
output: 'Employment.Position'
expression: '$1 + ", " + $2'
}
{
inputs: [
'$context(position).BaseSalary'
]
output: 'Employment.BaseSalary'
}
Пример карт:
- Сопоставление "один к одному"
BirthDate
напрямую сопоставляется безEmployee.DateOfBirth
преобразования. - Сопоставление "многие к одному": объединяет и
Office
вPosition
одноEmployment.Position
поле. Формула преобразования ($1 + ", " + $2
) объединяет эти поля в отформатированную строку. - Контекстные данные:
BaseSalary
добавляются из контекстного набора данных с именемposition
.
Ссылки на поля
Ссылки на поля показывают, как указать пути во входных и выходных данных с помощью нотации точек, например Employee.DateOfBirth
или доступа к данным из контекстного набора данных.$context(position)
Свойства пользователя MQTT
При использовании MQTT в качестве источника или назначения можно получить доступ к свойствам пользователя MQTT на языке сопоставления. Свойства пользователя можно сопоставить в входных или выходных данных.
В следующем примере свойство MQTT topic
сопоставляется с origin_topic
полем в выходных данных.
inputs: [
'$metadata.topic'
]
output: 'origin_topic'
Вы также можете сопоставить свойства MQTT с заголовком вывода. В следующем примере MQTT topic
сопоставляется с origin_topic
полем в свойстве пользователя выходных данных:
inputs: [
'$metadata.topic'
]
output: '$metadata.user_property.origin_topic'
Селекторы набора данных контекстуализации
Эти селекторы позволяют сопоставлениям интегрировать дополнительные данные из внешних баз данных, которые называются наборами данных контекстуализации.
Фильтрация записей
Фильтрация записей включает в себя настройку условий, чтобы выбрать, какие записи должны обрабатываться или удаляться.
Точечная нотация
Нотация точек широко используется в компьютерной науке для ссылок на поля, даже рекурсивно. В программировании имена полей обычно состоят из букв и чисел. Стандартный пример нотации точек может выглядеть следующим образом:
inputs: [
'Person.Address.Street.Number'
]
В потоке данных путь, описываемый нотацией точек, может включать строки и некоторые специальные символы, не требуя экранирования:
inputs: [
'Person.Date of Birth'
]
В других случаях требуется экранирование:
inputs: [
'Person."Tag.10".Value'
]
Предыдущий пример, среди других специальных символов, содержит точки в имени поля. Без экранирования имя поля будет служить разделителем в самой нотации точек.
Хотя поток данных анализирует путь, он обрабатывает только два символа как специальные:
- Точки (
.
) служат разделителями полей. - Одинарные кавычки при размещении в начале или конце сегмента запускают экранированный раздел, где точки не обрабатываются как разделители полей.
Любые другие символы обрабатываются как часть имени поля. Эта гибкость полезна в таких форматах, как JSON, где имена полей могут быть произвольными строками.
В Bicep все строки заключены в одинарные кавычки ('
). Примеры правильного кавыка в YAML для Kubernetes не применяются.
Экранирование
Основная функция экранирования в пути с точками заключается в использовании точек, которые являются частью имен полей, а не разделителей:
inputs: [
'Payload."Tag.10".Value'
]
В этом примере путь состоит из трех сегментов: Payload
, Tag.10
и Value
.
Экранирование правил в нотации точек
Escape каждый сегмент отдельно: если несколько сегментов содержат точки, эти сегменты должны быть заключены в двойные кавычки. Другие сегменты также могут быть процитированы, но это не влияет на интерпретацию пути:
inputs: [ 'Payload."Tag.10".Measurements."Vibration.$12".Value' ]
Правильное использование двойных кавычки: двойные кавычки должны открываться и закрывать экранируемый сегмент. Все кавычки в середине сегмента считаются частью имени поля:
inputs: [ 'Payload.He said: "Hello", and waved' ]
В этом примере определяются два поля: Payload
и He said: "Hello", and waved
. Когда точка появляется в этих обстоятельствах, она продолжает служить разделителем:
inputs: [
'Payload.He said: "No. It is done"'
]
В этом случае путь разбивается на сегменты Payload
и He said: "No
It is done"
(начиная с пробела).
Алгоритм сегментации
- Если первый символ сегмента является кавычками, средство синтаксического анализа выполняет поиск следующей кавычки. Строка, заключенная между этими кавычками, считается одним сегментом.
- Если сегмент не начинается с кавычки, средство синтаксического анализа определяет сегменты, выполняя поиск следующей точки или конца пути.
Подстановочный знак
Во многих сценариях запись выходных данных очень похожа на входную запись, при этом требуются только незначительные изменения. При использовании записей, содержащих многочисленные поля, вручную указание сопоставлений для каждого поля может стать емким. Подстановочные знаки упрощают этот процесс, позволяя обобщенным сопоставлениям, которые могут автоматически применяться к нескольким полям.
Рассмотрим базовый сценарий, чтобы понять использование звездочек в сопоставлениях:
inputs: [
'*'
]
output: '*'
Вот как звездочка (*
) работает в этом контексте:
- Сопоставление шаблонов: звездочка может соответствовать одному сегменту или нескольким сегментам пути. Он служит заполнителем для всех сегментов пути.
- Сопоставление полей: во время процесса сопоставления алгоритм вычисляет каждое поле в входной записи по шаблону, указанному в списке
inputs
. Звездочка в предыдущем примере соответствует всем возможным путям, эффективно соответствующих каждому отдельному полю в входных данных. - Захваченный сегмент: часть пути, который соответствует
captured segment
звездочку. - Сопоставление выходных данных: в выходной конфигурации
captured segment
помещается, где отображается звездочка. Это означает, что структура входных данных сохраняется в выходных данных сcaptured segment
заполнением заполнителя, предоставленного звездочкой.
Эта конфигурация демонстрирует наиболее универсальную форму сопоставления, где каждое поле во входных данных напрямую сопоставляется с соответствующим полем в выходных данных без изменения.
В другом примере показано, как можно использовать подстановочные знаки для сопоставления подразделов и их объединения. В этом примере эффективно плоские структуры вложенной структуры в объекте JSON.
Исходный КОД JSON:
{
"ColorProperties": {
"Hue": "blue",
"Saturation": "90%",
"Brightness": "50%",
"Opacity": "0.8"
},
"TextureProperties": {
"type": "fabric",
"SurfaceFeel": "soft",
"SurfaceAppearance": "matte",
"Pattern": "knitted"
}
}
Конфигурация сопоставления, использующая подстановочные знаки:
{
inputs: [
'ColorProperties.*'
]
output: '*'
}
{
inputs: [
'TextureProperties.*'
]
output: '*'
}
Результирующий JSON:
{
"Hue": "blue",
"Saturation": "90%",
"Brightness": "50%",
"Opacity": "0.8",
"type": "fabric",
"SurfaceFeel": "soft",
"SurfaceAppearance": "matte",
"Pattern": "knitted"
}
Размещение подстановочных знаков
При создании подстановочного знака необходимо соблюдать следующие правила:
- Один звездочку для каждого объекта dataDestination: допускается только одна звездочка (
*
) в пределах одного пути. - Полное сопоставление сегментов: звездочка всегда должна соответствовать всему сегменту пути. Его нельзя использовать для сопоставления только части сегмента, например
path1.partial*.path3
. - Размещение: звездочка может быть размещена в различных частях
dataDestination
:- В начале:
*.path2.path3
- Здесь звездочка соответствует любому сегменту, который приводит кpath2.path3
. - В середине:
path1.*.path3
— в этой конфигурации звездочка соответствует любому сегменту междуpath1
иpath3
. - В конце:
path1.path2.*
- Звездочка в конце соответствует любому сегменту, который следует послеpath1.path2
.
- В начале:
- Путь, содержащий звездочку, должен быть заключен в одинарные кавычки (
'
).
Подстановочные знаки с несколькими входными знаками
Исходный КОД JSON:
{
"Saturation": {
"Max": 0.42,
"Min": 0.67,
},
"Brightness": {
"Max": 0.78,
"Min": 0.93,
},
"Opacity": {
"Max": 0.88,
"Min": 0.91,
}
}
Конфигурация сопоставления, использующая подстановочные знаки:
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*'
expression: '($1 + $2) / 2'
Результирующий JSON:
{
"ColorProperties" : {
"Saturation": 0.54,
"Brightness": 0.85,
"Opacity": 0.89
}
}
Если вы используете подстановочные знаки с несколькими входными данными, звездочка (*
) должна постоянно представлять одинаковое Captured Segment
значение для каждого входного элемента. Например, при *
захвате Saturation
в шаблоне *.Max
алгоритм сопоставления ожидает соответствующего Saturation.Min
соответствия с шаблоном *.Min
. Ниже показано, *
как показано Captured Segment
в первом входе, задав сопоставление для последующих входных данных.
Рассмотрим этот подробный пример:
Исходный КОД 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
}
}
}
Начальная конфигурация сопоставления, использующая подстановочные знаки:
inputs: [
'*.Max' // - $1
'*.Min' // - $2
'*.Avg' // - $3
'*.Mean' // - $4
]
Это начальное сопоставление пытается создать массив (например, для Opacity
: [0.88, 0.91, 0.89, 0.89]
). Эта конфигурация завершается ошибкой, так как:
- Первый вход захватывает
*.Max
сегмент, напримерSaturation
. - Сопоставление ожидает, что последующие входные данные будут присутствовать на том же уровне:
Saturation.Max
Saturation.Min
Saturation.Avg
Saturation.Mean
Так как Avg
и Mean
вложены Mid
, звездочка в первоначальном сопоставлении неправильно фиксирует эти пути.
Исправленная конфигурация сопоставления:
inputs: [
'*.Max' // - $1
'*.Min' // - $2
'*.Mid.Avg' // - $3
'*.Mid.Mean' // - $4
]
Это измененное сопоставление точно фиксирует необходимые поля. Он правильно задает пути для включения вложенного Mid
объекта, что обеспечивает эффективную работу звездочек на разных уровнях структуры JSON.
Второе правило и специализация
При использовании предыдущего примера из подстановочных знаков с несколькими входными знаками следует учитывать следующие сопоставления, которые создают два производных значения для каждого свойства:
{
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*.Avg'
expression: '($1 + $2) / 2'
}
{
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*.Diff'
expression: 'abs($1 - $2)'
}
Это сопоставление предназначено для создания двух отдельных вычислений (Avg
и Diff
) для каждого свойства в разделе ColorProperties
. В этом примере показан результат:
{
"ColorProperties": {
"Saturation": {
"Avg": 0.54,
"Diff": 0.25
},
"Brightness": {
"Avg": 0.85,
"Diff": 0.15
},
"Opacity": {
"Avg": 0.89,
"Diff": 0.03
}
}
}
Здесь второе определение сопоставления для одних и того же входных данных действует как второе правило для сопоставления.
Теперь рассмотрим сценарий, в котором определенное поле требует другого вычисления:
{
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'
}
В этом случае Opacity
поле имеет уникальный расчет. Ниже приведены два варианта обработки этого перекрывающихся сценариев:
- Включите оба сопоставления для
Opacity
. Так как выходные поля отличаются в этом примере, они не переопределяют друг друга. - Используйте более конкретное правило для
Opacity
и удалите более универсальный.
Рассмотрим особый случай для того же поля, чтобы помочь решить правильное действие:
{
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*'
expression: '($1 + $2) / 2'
}
{
inputs: [
'Opacity.Max' // - $1
'Opacity.Min' // - $2
]
}
Пустое output
поле во втором определении подразумевает отсутствие записи полей в выходной записи (эффективное удаление Opacity
). Эта настройка больше, Specialization
чем .Second Rule
Разрешение перекрывающихся сопоставлений по потокам данных:
- Оценка выполняется из верхнего правила в определении сопоставления.
- Если новое сопоставление разрешается в те же поля, что и предыдущее правило, применяются следующие условия:
- Вычисляется
Rank
для каждого разрешенного ввода на основе количества сегментов записей подстановочных знаков. Например, если значениеCaptured Segments
Properties.Opacity
Rank
равно 2. Если это толькоOpacity
,Rank
значение равно 1. Сопоставление без подстановочных знаков имеетRank
значение 0. Rank
Если последнее правило равно или выше предыдущего правила, поток данных обрабатывает его как .Second Rule
- В противном случае поток данных обрабатывает конфигурацию как .
Specialization
- Вычисляется
Например, сопоставление, которое направляет Opacity.Max
пустой результат, Opacity.Min
имеет Rank
значение 0. Так как второе правило имеет меньше Rank
предыдущего, оно считается специализацией и переопределяет предыдущее правило, которое вычисляет значение для Opacity
.
Подстановочные знаки в наборах данных контекстуализации
Теперь давайте посмотрим, как наборы данных контекстуализации можно использовать с подстановочными знаками с помощью примера. Рассмотрим набор данных с именем position
, содержащий следующую запись:
{
"Position": "Analyst",
"BaseSalary": 70000,
"WorkingHours": "Regular"
}
В предыдущем примере мы использовали определенное поле из этого набора данных:
inputs: [
'$context(position).BaseSalary'
]
output: 'Employment.BaseSalary'
Это сопоставление копируется BaseSalary
из набора данных контекста непосредственно в Employment
раздел выходной записи. Если вы хотите автоматизировать процесс и включить все поля из position
набора данных в Employment
раздел, можно использовать подстановочные знаки:
inputs: [
'$context(position).*'
]
output: 'Employment.*'
Эта конфигурация позволяет динамическому сопоставлению, где каждое поле в position
наборе данных копируется в Employment
раздел выходной записи:
{
"Employment": {
"Position": "Analyst",
"BaseSalary": 70000,
"WorkingHours": "Regular"
}
}
Последнее известное значение
Можно отслеживать последнее известное значение свойства. Суффикс поле ввода с ? $last
записью последнего известного значения поля. Если свойство отсутствует в последующих входных полезных данных, последнее известное значение сопоставляется с выходными полезными данными.
Например, рассмотрим следующее сопоставление:
inputs: [
'Temperature ? $last'
]
output: 'Thermostat.Temperature'
В этом примере отслеживается последнее известное значение Temperature
. Если последующие входные полезные данные не содержат Temperature
значения, в выходных данных используется последнее известное значение.