Бөлісу құралы:


Сопоставление данных с помощью потоков данных

Внимание

Предварительная версия операций Интернета вещей 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: "NoIt 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.OpacityRank равно 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 значения, в выходных данных используется последнее известное значение.