Поделиться через


Запрос данных о графе двойника Azure Digital Twins

В этой статье приведены примеры и инструкции по использованию языка запросов Azure Digital Twins для запроса информации в графе двойников. (Базовые сведения о языке запросов см. в этой статье.)

В этой статье приведены примеры, иллюстрирующие структуру языка запросов и общие операции запросов к цифровым двойникам. В нем также описывается, как выполнять запросы после их записи с помощью API запросов Azure Digital Twins или пакета SDK.

Примечание.

При выполнении следующих примеров запросов с вызовом API или ПАКЕТА SDK необходимо сжать текст запроса в одну строку.

Справочная документация

Справочник по языку запросов можно найти в разделе Reference в левом оглавлении документации по Azure Digital Twins. Вы также можете перейти непосредственно к справочным разделам, используя приведенные ниже ссылки:

Отображение всех цифровых двойников

Ниже приведен базовый запрос, который возвращает список всех цифровых двойников в экземпляре:

SELECT * FROM DIGITALTWINS

Запрос по свойству

Получите цифровых двойников по свойствам (включая идентификатор и метаданные):

SELECT  *
FROM DIGITALTWINS T  
WHERE T.firmwareVersion = '1.1'
AND T.$dtId in ['123', '456']
AND T.Temperature = 70

Как показано в предыдущем запросе, идентификатор цифрового двойника запрашивается с помощью поля $dtIdметаданных.

Совет

Если вы используете Cloud Shell для выполнения запроса с полями метаданных, которые начинаются с $, следует поставить обратную косую черту перед $, чтобы дать Cloud Shell знать, что это не переменная, и его следует интерпретировать как литерал в тексте запроса.

Вы также можете получить двойников в зависимости от того, определено ли конкретное свойство. Ниже приведен запрос, который получает двойники с определенным Location свойством:

SELECT * FROM DIGITALTWINS WHERE IS_DEFINED(Location)

Этот запрос поможет получить двойников по их tag свойствам, как описано в разделе "Добавление тегов в цифровые двойники". Вот запрос, который получает все двойники, помеченные тегом red:

SELECT * FROM DIGITALTWINS WHERE IS_DEFINED(tags.red)

Двойников можно также получить на основе типа свойства. Ниже приведен запрос, который получает двойников, свойство которого Temperature является числом:

SELECT * FROM DIGITALTWINS T WHERE IS_NUMBER(T.Temperature)

Свойства карты запросов

Если свойство имеет сложный тип Map, вы можете использовать ключи и значения карты непосредственно в запросе, например:

SELECT * FROM DIGITALTWINS T WHERE T.<propertyName>.<mapKey> = '<mapValue>'

Если ключ карты начинается с числового символа, необходимо упаковать ключ в двойные квадратные скобки ([[<mapKey>]]), чтобы экранировать его в запросе, аналогично стратегии запроса с зарезервированными ключевыми словами.

Запрос по модели

Для фильтрования по IS_OF_MODEL двойника можно использовать оператор .

Он рассматривает наследование и управление версиями моделей и оценивается true для данного двойника, если двойник соответствует любой из следующих условий:

  • Двойник напрямую реализует модель, указанную для IS_OF_MODEL(), а номер версии модели в двойнике больше или равен номеру версии предоставленной модели.
  • Близнец реализует модель, которая расширяет предоставленную модель IS_OF_MODEL(), и номер версии расширенной модели близнеца больше или равен номеру версии предоставленной модели.

Например, если вы делаете запрос на двойников модели dtmi:example:widget;4, этот запрос возвращает всех двойников, основанных на версии 4 или более поздней модели виджета, а также двойников, основанных на версии 4 или выше любой модели, наследующейся от виджета.

IS_OF_MODEL может принимать несколько различных параметров, и остальная часть этого раздела будет посвящена различным вариантам перегрузки.

Самый простой способ использования IS_OF_MODEL — это принимать только параметр twinTypeName: IS_OF_MODEL(twinTypeName). Ниже приведен пример запроса, который передает значение в этом параметре.

SELECT * FROM DIGITALTWINS WHERE IS_OF_MODEL('dtmi:example:thing;1')

Чтобы указать коллекцию двойников для поиска при наличии нескольких элементов (например, если используется JOIN), добавьте параметр twinCollection: IS_OF_MODEL(twinCollection, twinTypeName). Ниже приведен пример запроса, который добавляет значение для этого параметра.

SELECT * FROM DIGITALTWINS DT WHERE IS_OF_MODEL(DT, 'dtmi:example:thing;1')

Для поиска точного соответствия добавьте параметр exact: IS_OF_MODEL(twinTypeName, exact). Ниже приведен пример запроса, который добавляет значение для этого параметра.

SELECT * FROM DIGITALTWINS WHERE IS_OF_MODEL('dtmi:example:thing;1', exact)

Можно также передать все три аргумента вместе: IS_OF_MODEL(twinCollection, twinTypeName, exact). Ниже приведен пример запроса, в котором указывается значение для всех трех параметров.

SELECT * FROM DIGITALTWINS DT WHERE IS_OF_MODEL(DT, 'dtmi:example:thing;1', exact)

Запрос по связи

Для запроса на основе связей цифровых двойников язык запросов Azure Digital Twins предоставляет специальный синтаксис.

Связи включаются в область запроса в клаузе FROM. В отличие от "классических" языков SQL, каждое выражение в предложении FROM не является таблицей; вместо этого предложение FROM выражает результат обхода перекрестных связей между сущностями. Для обхода связей в Azure Digital Twins используется пользовательская версия JOIN.

Помните, что с возможностями Azure Digital Twins модели связи не могут существовать отдельно от двойников. Результатом является то, что связи не могут запрашиваться независимо и должны быть привязаны к двойнику. Для отражения этого факта в предложении RELATED используется ключевое слово JOIN, чтобы извлечь набор связей определенного типа, поступающий из коллекции двойников. Затем запрос должен быть отфильтрован в WHERE предложении, чтобы указать, какие конкретные близнецы следует использовать в запросе связи (используя значения близнецов $dtId).

В разделах ниже приведены примеры того, как это выглядит.

Базовый запрос связей

Вот пример реляционного запроса. Этот фрагмент кода выбирает все цифровые двойники со свойством IDABC, и все цифровые двойники, связанные с этими цифровыми двойниками через связь contains.

SELECT T, CT
FROM DIGITALTWINS T
JOIN CT RELATED T.contains
WHERE T.$dtId = 'ABC'

Тип связи (contains в предыдущем примере) указывается с помощью поля связи name из определения DTDL.

Примечание.

Разработчику не нужно сопоставлять это JOIN со значением ключа в WHERE предложении (или указывать значение ключа в соответствии с определением JOIN ). Система автоматически вычисляет эту корреляцию, так как свойства связи сами определяют целевую сущность.

Запрос по источнику или целевому объекту связи

Структуру запроса связей можно использовать для определения цифрового двойника, который является источником или целевым объектом связи.

Например, можно начать с исходного двойника и следовать его связям, чтобы найти целевые двойники этих связей. Ниже приведен пример запроса, который находит целевые объекты feeds, связанные с исходным двойником.

SELECT target 
FROM DIGITALTWINS source 
JOIN target RELATED source.feeds 
WHERE source.$dtId = 'source-twin'

Также можно начать с целевого объекта связи и отследить ее в обратном направлении, чтобы найти двойник источника. Ниже приведен пример запроса, который находит исходный двойник feeds связи по отношению к целевому двойнику.

SELECT source 
FROM DIGITALTWINS source 
JOIN target RELATED source.feeds 
WHERE target.$dtId = 'target-twin'

Запрос свойств связи

Аналогично тому, как цифровые двойники имеют свойства, описанные с помощью DTDL, связи также могут иметь свойства. Двойников можно запрашивать в зависимости от свойств их связей. Язык запросов Azure Digital Twins позволяет фильтровать и проецировать связи, назначая связи псевдоним в предложении JOIN.

В качестве примера, рассмотрим servicedBy отношение, которое имеет свойство reportedCondition. В следующем запросе эта связь предоставляется псевдонимом R для ссылки на её свойство.

SELECT T, SBT, R
FROM DIGITALTWINS T
JOIN SBT RELATED T.servicedBy R
WHERE T.$dtId = 'ABC'
AND R.reportedCondition = 'clean'

В предыдущем примере обратите внимание, как reportedCondition является свойством servicedBy самой связи (НЕ какого-то цифрового двойника, имеющего servicedBy отношение).

Запрос с несколькими объединениями (JOIN)

В одном запросе поддерживается до пяти предложений JOIN, что позволяет одновременно обходить несколько уровней связей.

Чтобы запросить несколько уровней связей, используйте одну инструкцию FROM, за которой следуют n инструкций JOIN, где инструкции JOIN выражают связи с результатом предыдущей инструкции FROM или JOIN.

Ниже приведен пример запроса с несколькими объединениями, который получает все лампочки, содержащиеся в световых панелях в комнатах 1 и 2.

SELECT LightBulb
FROM DIGITALTWINS Room
JOIN LightPanel RELATED Room.contains
JOIN LightBulb RELATED LightPanel.contains
WHERE IS_OF_MODEL(LightPanel, 'dtmi:contoso:com:lightpanel;1')
AND IS_OF_MODEL(LightBulb, 'dtmi:contoso:com:lightbulb ;1')
AND Room.$dtId IN ['room1', 'room2']

Подсчет элементов

Количество элементов в результирующем наборе можно подсчитать с помощью предложения Select COUNT:

SELECT COUNT()
FROM DIGITALTWINS

Добавьте предложение WHERE для подсчета количества элементов, соответствующих определенным критериям. В следующих примерах показан подсчет с применением фильтра на основе типа твин-модели. Дополнительные сведения об этом синтаксисе см. в разделе "Запрос по модели".

SELECT COUNT()
FROM DIGITALTWINS
WHERE IS_OF_MODEL('dtmi:sample:Room;1')

SELECT COUNT()
FROM DIGITALTWINS c
WHERE IS_OF_MODEL('dtmi:sample:Room;1') AND c.Capacity > 20

Также можно использовать COUNT вместе с конструкцией JOIN. Ниже приведен запрос, который подсчитывает все лампочки в панелях освещения в помещениях 1 и 2:

SELECT COUNT()  
FROM DIGITALTWINS Room  
JOIN LightPanel RELATED Room.contains  
JOIN LightBulb RELATED LightPanel.contains  
WHERE IS_OF_MODEL(LightPanel, 'dtmi:contoso:com:lightpanel;1')  
AND IS_OF_MODEL(LightBulb, 'dtmi:contoso:com:lightbulb;1')  
AND Room.$dtId IN ['room1', 'room2']

Фильтрация результатов: выбор первых элементов

С помощью предложения Select TOP можно выбрать несколько "первых" элементов в запросе.

SELECT TOP (5)
FROM DIGITALTWINS
WHERE ...

Фильтрация результатов: задайте возвращаемый набор с проекциями

С помощью проекций в инструкции SELECT можно выбрать столбцы, возвращаемые запросом. Проекция теперь поддерживается как для простых, так и для сложных свойств. Дополнительные сведения о проекциях в Azure Digital Twins можно найти в справочной документации по конструкции SELECT.

Ниже приведен пример запроса, который использует проекцию для возврата двойников и связей. Следующий запрос отображает потребителя, фабрику и пограничные устройства из сценария, в котором фабрика с идентификатором ABC связана с потребителем через связь Factory.customer, и эта связь представлена как Edge.

SELECT Consumer, Factory, Edge
FROM DIGITALTWINS Factory
JOIN Consumer RELATED Factory.customer Edge
WHERE Factory.$dtId = 'ABC'

Можно также использовать проекцию для возврата свойства двойника. Следующий запрос проектирует свойство Name потребителей, которые связаны с фабрикой с идентификатором ABC через связь Factory.customer.

SELECT Consumer.name
FROM DIGITALTWINS Factory
JOIN Consumer RELATED Factory.customer Edge
WHERE Factory.$dtId = 'ABC'

Можно также использовать проекцию для возврата свойства связи. Как и в предыдущем примере, следующий запрос проецирует свойство Name потребителей, связанных с фабрикой с идентификатором ABC через связь Factory.customer; но теперь он также возвращает два свойства этой связи, prop1 и prop2. Запрос возвращает те два свойства, именуя связь Edge и собирая свойства этой связи.

SELECT Consumer.name, Edge.prop1, Edge.prop2, Factory.area
FROM DIGITALTWINS Factory
JOIN Consumer RELATED Factory.customer Edge
WHERE Factory.$dtId = 'ABC'

Можно также использовать псевдонимы для упрощения запросов с помощью проекции.

Следующий запрос выполняет те же операции, что и предыдущий пример, но присваивает имена свойствам — consumerName, first, second и factoryArea.

SELECT Consumer.name AS consumerName, Edge.prop1 AS first, Edge.prop2 AS second, Factory.area AS factoryArea
FROM DIGITALTWINS Factory
JOIN Consumer RELATED Factory.customer Edge
WHERE Factory.$dtId = 'ABC'

Ниже приведен аналогичный запрос, который запрашивает тот же набор, что и предыдущий запрос, но проектирует только Consumer.name свойство как consumerName, и проектирует полную Фабрику в виде двойника.

SELECT Consumer.name AS consumerName, Factory
FROM DIGITALTWINS Factory
JOIN Consumer RELATED Factory.customer Edge
WHERE Factory.$dtId = 'ABC'

Создание эффективных запросов с помощью оператора IN

Можно значительно сократить количество необходимых запросов, создав массив двойников и выполняя запросы с помощью оператора IN.

Например, рассмотрим ситуацию, в которой здания содержат этажи, а этажи содержат комнаты. Вот один из способов поиска отапливаемых помещений в здании.

  1. Поиск этажей в здании на основе связи contains.

    SELECT Floor
    FROM DIGITALTWINS Building
    JOIN Floor RELATED Building.contains
    WHERE Building.$dtId = @buildingId
    
  2. Чтобы найти комнаты, вместо рассмотрения этажей по одному и выполнения JOIN запроса, чтобы найти комнаты для каждого из них, вы можете запросить коллекцию этажей в здании (с именем Floor в следующем запросе).

    В клиентском приложении:

    var floors = "['floor1','floor2', ..'floorn']"; 
    

    В запросе:

    SELECT Room
    FROM DIGITALTWINS Floor
    JOIN Room RELATED Floor.contains
    WHERE Floor.$dtId IN ['floor1','floor2', ..'floorn']
    AND Room. Temperature > 72
    AND IS_OF_MODEL(Room, 'dtmi:com:contoso:Room;1')
    

Другие примеры составных запросов

Вы можете объединить любой из ранее описанных типов запросов с помощью операторов сочетаний, чтобы включить более подробную информацию в один запрос. Ниже приведены некоторые другие примеры составных запросов, которые одновременно запрашивают дескрипторы двойников сразу нескольких типов.

  • Из устройств, находящихся в комнате 123, верните устройства MxChip, которые выполняют роль оператора.
    SELECT device
    FROM DIGITALTWINS space
    JOIN device RELATED space.has
    WHERE space.$dtid = 'Room 123'
    AND device.$metadata.model = 'dtmi:contoso:com:DigitalTwins:MxChip:3'
    AND has.role = 'Operator'
    
  • Получите близнецов, которые имеют связь Contains с другим близнецом с идентификатором id1.
    SELECT Room
    FROM DIGITALTWINS Room
    JOIN Thermostat RELATED Room.Contains
    WHERE Thermostat.$dtId = 'id1'
    
  • Получите все комнаты этой модели, которые находятся на этаже floor11
    SELECT Room
    FROM DIGITALTWINS Floor
    JOIN Room RELATED Floor.Contains
    WHERE Floor.$dtId = 'floor11'
    AND IS_OF_MODEL(Room, 'dtmi:contoso:com:DigitalTwins:Room;1')
    

Выполнение запросов с помощью API

После принятия решения о строке запроса его выполнение выполняется путем вызова API запросов.

Вы можете напрямую вызывать API или использовать один из пакетов SDK, доступных для Azure Digital Twins.

В следующем фрагменте кода показан вызов пакета SDK для .NET (C#) из клиентского приложения:

// Run a query for all twins   
string query = "SELECT * FROM DIGITALTWINS";
AsyncPageable<BasicDigitalTwin> result = client.QueryAsync<BasicDigitalTwin>(query);

Запрос, используемый в этом вызове, возвращает список цифровых двойников, который в предыдущем примере представляется с объектами BasicDigitalTwin . Тип возвращаемых данных для каждого запроса зависит от того, какие термины указываются с помощью инструкции SELECT :

  • Запросы, начинающиеся с SELECT * FROM ..., возвращают список цифровых двойников (которые можно сериализовать как BasicDigitalTwin объекты или другие пользовательские типы цифровых двойников, которые могут быть созданы).
  • Запросы, начинающиеся в форматеSELECT <A>, <B>, <C> FROM ..., возвращают словарь с ключами <A>и <B><C>.
  • Можно создавать другие типы инструкций SELECT, чтобы возвращать пользовательские данные. Вы можете создать собственные классы для обработки настраиваемых результирующих наборов.

Запрос с разбивкой на страницы

Запросы поддерживают постраничную навигацию. Ниже приведен полный пример использования BasicDigitalTwin в качестве типа результата запроса с обработкой ошибок и разбивкой на страницы.

AsyncPageable<BasicDigitalTwin> result = client.QueryAsync<BasicDigitalTwin>("Select * From DigitalTwins");
try
{
    await foreach (BasicDigitalTwin twin in result)
    {
        // You can include your own logic to print the result
        // The logic below prints the twin's ID and contents
        Console.WriteLine($"Twin ID: {twin.Id} \nTwin data");
        foreach (KeyValuePair<string, object> kvp in twin.Contents)
        {
            Console.WriteLine($"{kvp.Key}  {kvp.Value}");
        }
    }
}
catch (RequestFailedException ex)
{
    Console.WriteLine($"Error {ex.Status}, {ex.ErrorCode}, {ex.Message}");
    throw;
}

Следующие шаги

Узнайте подробнее об API-интерфейсах и пакетах SDK Azure Digital Twins, включая API запросов, который используется для выполнения запросов из этой статьи.