你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

查询 Azure 数字孪生孪生图

本文提供了查询示例和说明来介绍如何使用 Azure 数字孪生查询语言查询孪生图以获取信息。 (如需查询语言简介,请参阅查询语言。)

本文包含示例查询,它们说明了数字孪生体的查询语言结构和常见查询操作。 它还介绍如何使用 Azure 数字孪生查询 APISDK 在编写查询后运行查询。

注意

如果通过 API 或 SDK 调用运行以下示例查询,则需将查询文本压缩为一行。

参考文档

可以在“Azure 数字孪生”文档左侧目录中的“引用”下找到查询语言引用。 还可以使用如下链接直接跳转到“引用”部分:

显示所有数字孪生

下面是基本查询,它将会返回该实例中所有数字孪生体的列表:

SELECT * FROM DIGITALTWINS

按属性查询

按属性(包括 ID 和元数据)获取数字孪生:

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

如以上查询所示,将使用元数据字段 $dtId 查询数字孪生体的 ID。

提示

如果使用 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 数字孪生查询语言有一个特殊的语法。

关系将被拉取到 FROM 子句中的查询范围内。 与“经典”SQL 类型语言不同,FROM 子句中的每个表达式都不是表;更确切地说,FROM 子句表达的是跨实体关系遍历。 为了跨关系遍历,Azure 数字孪生使用自定义版本的 JOIN

请回忆一下,在使用 Azure 数字孪生模型功能时,关系不是独立于孪生而存在的,这就意味着此处的关系不能单独被查询,而是必须绑定到某个孪生体。 为了反映这个事实,在 JOIN 子句中使用了关键字 RELATED,以便在来自孪生体集合的某种特定类型关系的集中拉取。 然后,该查询必须在 WHERE 子句中筛选,以指明要在关系查询中使用哪个(些)特定孪生体(使用孪生体的 $dtId 值)。

下节提供了示例进行介绍。

基本关系查询

下面是基于示例关系的查询。 此代码片段选择 ID 属性为 ABC 的所有数字孪生体,以及所有通过 contains 关系与这些数字孪生体相关的数字孪生体。

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

关系的类型(上述示例中的 contains)是通过使用来自关系的 DTDL 定义name 字段来指明的。

注意

开发人员无需将此 JOINWHERE 子句中的键值相关联(也不需要使用 JOIN 定义以内联方式指定键值)。 此关联由系统自动计算,因为关系属性本身标识目标实体。

按关系的源或目标进行查询

可使用关系查询结构来标识作为关系的源或目标的数字孪生体。

例如,你可从源孪生体开始,然后按照其关系查找关系的目标孪生体。 下面的查询示例查找来自孪生体 source-twin 的 feeds 关系的目标孪生体。

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

也可以从关系的目标开始,追溯关系以查找源孪生体。 下面的查询示例查找孪生体 target-twin 的 feeds 关系的源孪生体。

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

查询关系的属性

与数字孪生体通过 DTDL 描述属性的方式类似,关系也可以具有属性。 可根据孪生体关系的属性查询孪生体。 使用 Azure 数字孪生查询语言,可以通过在 JOIN 子句中将别名分配给关系来筛选和投影关系。

例如,考虑具有 reportedCondition 属性的 servicedBy 关系。 在下面的查询中,将为此关系提供一个别名 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 语句,然后使用多个 JOIN 语句,其中 JOIN 语句表示与先前 FROMJOIN 语句的结果相关的关系。

下面是多联接查询的示例,它获取房间 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

还可以将 COUNTJOIN 子句结合使用。 下面的查询统计房间 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 数字孪生投影的详细信息,请参阅 SELECT 子句参考文档

下面的查询示例使用投影来返回孪生体和关系。 以下查询对方案中的 Consumer、Factory 和 Edge 进行了投影,其中 ID 为 ABC 的 Factory 通过 Factory.customer 关系与 Consumer 相关联,而该关系表示为 Edge

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

你还可以使用投影返回孪生的属性。 以下查询对 Consumer 的 Name 属性进行了投影,这些 Consumer 通过 Factory.customer 关系与 ID 为 ABC 的 Factory 相关联。

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

你还可以使用投影返回关系的属性。 与先前的示例类似,以下查询对 Consumer 的 Name 属性进行了投影,这些 Consumer 通过 Factory.customer 关系与 ID 为 ABC 的 Factory 相关联;但现在查询还返回了该关系的两个属性 prop1prop2。 它通过将关系命名为 Edge 并收集其属性来实现这一点。

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

你也可以使用别名来简化使用投影的查询。

以下查询执行与先前示例相同的操作,但会对属性名称采用以下别名:consumerNamefirstsecondfactoryArea

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,并将整个 Factory 投影为孪生体。

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 查询查找每个楼层的房间。

    在客户端应用中:

    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 关系的孪生体,以及 ID 为 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,也可以使用适用于 Azure 数字孪生的其中一个 SDK

以下代码片段说明了客户端应用中的 .NET (C#) SDK 调用:

// 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;
}

后续步骤

详细了解 Azure 数字孪生 API 和 SDK,包括本文中用于运行查询的查询 API。