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


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

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

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

Примечание

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

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

Справочные материалы по языку запросов можно найти в разделе Справочные материалы в левой части раздела с документацией по 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 отношения не существуют независимо от двойников, что означает, что связи здесь нельзя запрашивать отдельно — они должны быть привязаны к двойникам. Для отражения этого факта в предложении JOIN используется ключевое слово RELATED, чтобы извлечь набор связей определенного типа, поступающий из коллекции двойников. Затем запрос должен применить фильтр в предложении 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 связи с двойником target-twin.

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.

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

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

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

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

Можно также использовать проекцию для возврата свойства связи. Как и в предыдущем примере, следующий запрос проецировать Name свойство объекта Consumers, связанное с фабрикой, с идентификатором 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.

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

  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')
    

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

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

  • Возврат устройств MxChip, выступающих в роли оператора, из числа устройств, на которых имеется Room 123.
    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 запросов, который используется для выполнения запросов из этой статьи.