你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
查询 Azure 数字孪生孪生图
本文提供了查询示例和说明来介绍如何使用 Azure 数字孪生查询语言查询孪生图以获取信息。 (如需查询语言简介,请参阅查询语言。)
本文包含示例查询,它们说明了数字孪生体的查询语言结构和常见查询操作。 它还介绍如何使用 Azure 数字孪生查询 API 或 SDK 在编写查询后运行查询。
注意
如果通过 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
字段来指明的。
注意
开发人员无需将此 JOIN
与 WHERE
子句中的键值相关联(也不需要使用 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
语句表示与先前 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 数字孪生投影的详细信息,请参阅 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 相关联;但现在查询还返回了该关系的两个属性 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
,并将整个 Factory 投影为孪生体。
SELECT Consumer.name AS consumerName, Factory
FROM DIGITALTWINS Factory
JOIN Consumer RELATED Factory.customer Edge
WHERE Factory.$dtId = 'ABC'
使用 IN 运算符生成高效的查询
通过使用 IN
运算符生成孪生数组并进行查询,可以大大减少所需的查询数。
例如,假设建筑物包含楼层,而楼层包含房间 。 若要搜索建筑物内室温高的房间,可以按照以下步骤进行操作。
根据
contains
关系查找建筑物中的楼层。SELECT Floor FROM DIGITALTWINS Building JOIN Floor RELATED Building.contains WHERE Building.$dtId = @buildingId
若要查找房间,可以查询建筑物中楼层的集合(以下查询中命名为“楼层”),而不是考虑逐个楼层并运行
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。