IoT 中樞提供功能強大、類似 SQL 的語言,以擷取有關裝置對應項、模組對應項、作業和訊息路由的資訊。 本文介紹:
- 介紹 IoT 中樞 查詢語言的主要功能。
- 語言的詳細描述。 如需訊息路由查詢語言的詳細資訊,請參閱 IoT中樞訊息路由查詢語法。
如需特定範例,請參閱 IoT中樞裝置和模組對應項的查詢 或 IoT中樞作業的查詢。
附註
本文中提及的某些功能 (例如雲端對裝置傳訊、裝置對應項和裝置管理) 僅適用於 IoT 中樞的標準層。 如需有關基本和標準/免費 IoT 中樞服務層級的詳細資訊,請參閱為您的解決方案選擇合適的 IoT 中樞層和大小 (英文)。
執行 IoT 中樞查詢
您可以直接在 Azure 入口網站中對 IoT 中樞執行查詢。
- 登入 Azure 入口網站,然後瀏覽至 IoT 中樞。
- 從導覽功能表的 [裝置管理] 區段中選取 [查詢]。
- 保留預先填入的
SELECT * FROM devices查詢以擷取裝置對應項,或以您自己的查詢加以取代。 - 選擇 執行查詢 以顯示結果。
Important
裝置 頁面的 搜尋與篩選,以及 查詢 頁面的查詢,最終會使用一致的資料。 新建立的裝置和最近的 twin 變更可能不會立即顯示,刪除的裝置也可能暫時保留在結果中。 要檢查已知裝置目前的 twin 值,請直接使用 Get Twin 請求,而不是查詢。 欲了解更多資訊,請參閱 Twin 查詢限制。
您也可以使用 Azure IoT 服務 SDK 和服務 API,在應用程式中執行查詢。
如需實作 IoT 中樞查詢的範例程式碼,請參閱使用服務 SDK 的查詢範例一節。
如需 SDK 參考頁面和範例的連結,請參閱 Azure IoT 中樞 SDK。
IoT 中樞查詢的基本概念
每個「IoT 中樞」查詢都包含 SELECT 和 FROM 子句,以及選擇性的 WHERE 和 GROUP BY 子句。
查詢都會在 JSON 文件的集合上執行,例如裝置對應項。 FROM 子句會指出要在其上反覆運算的文件集合 (devices、devices.modules 或 devices.jobs)。
然後,會套用 WHERE 子句中的篩選。 使用彙總時,此步驟的結果會依照 GROUP BY 子句中所指定的方式進行分組。 針對每個群組,會依照 SELECT 子句中所指定的方式產生一個資料列。
SELECT <select_list>
FROM <from_specification>
[WHERE <filter_condition>]
[GROUP BY <group_specification>]
SELECT 子句
每個IoT 中樞查詢都必須有 SELECT <select_list> 子句。 該子句會指定要從查詢中擷取哪些值。 它會指定用來產生新 JSON 物件的 JSON 值。
針對已篩選 (及視需要已分組) 之 FROM 集合子集的每個項目,投影階段會產生一個新的 JSON 物件。 此物件會以 SELECT 子句中所指定的值來建構。
例如:
傳回所有值
SELECT *傳回特定屬性
SELECT DeviceID, LastActivityTime彙總查詢的結果以傳回計數
SELECT COUNT() as TotalNumber
目前,除SELECT之外的選擇子句僅支援於裝置雙生的彙總查詢中。
下列語法是 SELECT 子句的文法︰
SELECT [TOP <max number>] <projection list>
<projection_list> ::=
'*'
| <projection_element> AS alias [, <projection_element> AS alias]+
<projection_element> :==
attribute_name
| <projection_element> '.' attribute_name
| <aggregate>
<aggregate> :==
count()
| avg(<projection_element>)
| sum(<projection_element>)
| min(<projection_element>)
| max(<projection_element>)
Attribute_name 指的是 FROM 集合中 JSON 文件的任何屬性。
FROM 子句
這個 FROM <from_specification> 子句在每個 ioT Hub 查詢中都是必填的。 必須是下列三個值中的其中一個:
- devices,用來查詢裝置對應項
- devices.modules,用來查詢模組對應項
- devices.jobs,用來查詢每個裝置的作業詳細資料
例如:
擷取所有裝置對應項
SELECT * FROM devices
WHERE 子句
該 WHERE <filter_condition> 條款為可選條款。 它會指定一或多個條件,而且 FROM 集合中的 JSON 文件必須滿足這些條件,才能納入為結果的一部分。 任何 JSON 文件都必須將指定的條件評估為 真 ,才能納入結果中。
例如:
擷取以特定裝置為目標的所有作業
SELECT * FROM devices.jobs WHERE devices.jobs.deviceId = 'myDeviceId'
允許的條件會在 表達式和條件 一節中描述。
GROUP BY 子句
該 GROUP BY <group_specification> 條款為可選條款。 此子句會在 WHERE 子句中指定的篩選之後、SELECT 中指定的投影之前執行。 它會根據屬性值來分組文件。 這些群組可用來產生 SELECT 子句中所指定的彙總值。
例如:
傳回報告每個遙測設定狀態的裝置計數
SELECT properties.reported.telemetryConfig.status AS status, COUNT() AS numberOfDevices FROM devices GROUP BY properties.reported.telemetryConfig.status
目前,GROUP BY 子句只支援在查詢裝置孿生時使用。
警告
目前, 「群組 」一詞在查詢中被視為特殊關鍵字。 萬一使用 group 作為屬性名稱,請考慮以雙括弧括住它以避免錯誤,如下列範例所示: SELECT * FROM devices WHERE tags.[[group]].name = 'some_value'。
GROUP BY 的正式語法如下︰
GROUP BY <group_by_element>
<group_by_element> :==
attribute_name
| < group_by_element > '.' attribute_name
Attribute_name 指的是 FROM 集合中 JSON 文件的任何屬性。
查詢結果分頁
查詢結果分頁與 Azure 入口網站中的預設 裝置 清單分開,後者最多會顯示 15 台裝置,且不提供完整裝置清查的分頁功能。 使用服務 SDK 列舉查詢結果時,請持續請求頁面,直到沒有其他結果可用為止。
查詢物件會以小於或等於 100 筆記錄的最大頁面大小 具現化。 若要取得多個頁面,請在 Node.js SDK 上呼叫 nextAsTwin ,或在 .NET SDK 方法上呼叫 GetNextAsTwinAsync 多次。 query 物件可根據查詢所需的還原序列化選項,公開多個 Next 值。 例如,查詢物件可以傳回裝置孿生或作業物件,或者在使用投影時傳回純 JSON。
運算式和條件
概括而言,運算式:
- 會評估為 JSON 類型 (例如布林值、數字、字串、陣列或物件) 的執行個體。
- 定義方式是使用內建運算子和函式處理來自裝置 JSON 文件和常數的資料。
「條件」是評估為布林值的運算式。 任何與布林值 true 不同的常數都會被視為 false。 此規則包括 nullundefined、任何物件或陣列實例、任何字串,以及布林值 false。
運算式的語法如下:
<expression> ::=
<constant> |
attribute_name |
<function_call> |
<expression> binary_operator <expression> |
<create_array_expression> |
'(' <expression> ')'
<function_call> ::=
<function_name> '(' expression ')'
<constant> ::=
<undefined_constant>
| <null_constant>
| <number_constant>
| <string_constant>
| <array_constant>
<undefined_constant> ::= undefined
<null_constant> ::= null
<number_constant> ::= decimal_literal | hexadecimal_literal
<string_constant> ::= string_literal
<array_constant> ::= '[' <constant> [, <constant>]+ ']'
若要了解運算式語法中每個符號所代表的意義,請參閱下表:
| 符號 | 定義 |
|---|---|
| 屬性名稱 | FROM 集合中 JSON 文件的任何屬性。 |
| binary_operator | 運算子一節中所列的任何二元運算子。 |
| function_name | 函式一節中所列的任何函式。 |
| decimal_literal | 以小數點標記法表示的浮點數字。 |
| hexadecimal_literal | 以字串 '0x' 開頭並跟隨一串十六進位數字的字串所表示的數字。 |
| string_literal | 由零個或多個 Unicode 字元序列或逸出序列所表示的 Unicode 字串。 字串常值會以單引號或雙引號括起來。 允許的逸出︰\'、\"、\\、\uXXXX (適用於由四個十六進位數字所定義的 Unicode 字元)。 |
操作員
支援下列運算子:
| 家庭 | 操作員 |
|---|---|
| 算術 | +、-、*、/、% |
| 邏輯 | AND、OR、NOT |
| 比較 | =、!=、<、>、<=、>=、<> |
Functions
查詢對應項和作業時唯一支援的函式為:
| 功能 | 描述 |
|---|---|
| IS_DEFINED(property) | 傳回布爾值,指出屬性是否已指派值(包括 null)。 |
在路由條件中,支援下列比對函式:
| 功能 | 描述 |
|---|---|
| ABS(x) | 傳回指定之數值運算式的絕對 (正) 值。 |
| EXP(x) | 傳回指定之數值運算式 (e^x) 的指數值。 |
| POWER(x,y) | 將指定之運算式的值傳回給指定的乘冪 (x^y)。 |
| SQUARE(x) | 傳回指定之數值的平方。 |
| CEILING(x) | 傳回大於或等於指定之數值運算式的最小整數值。 |
| FLOOR(x) | 傳回小於或等於指定數值運算式的最大整數。 |
| SIGN(x) | 傳回指定之數值運算式的正數 (+1)、零 (0) 或負數 (-1) 符號。 |
| SQRT(x) | 傳回指定之數值的平方根。 |
在路由條件中,支援下列類型檢查和轉換函式:
| 功能 | 描述 |
|---|---|
| AS_NUMBER | 將輸入字串轉換為數字。 如果輸入是一個數字則為 noop;如果字串不是數字則為 Undefined。 |
| IS_ARRAY | 傳回布林值,表示指定之運算式的類型為陣列。 |
| IS_BOOL | 傳回一個布林值,以指示指定運算式的型別是否為布林值。 |
| IS_DEFINED | 傳回布爾值,指出屬性是否為值。 只有在值是基本類型時,才支援此函式。 基本類型包括字串、布林值、數值或 null。 不支援 DateTime、物件類型和陣列。 |
| IS_NULL | 傳回布林值,表示指定之運算式的型別為 null。 |
| IS_NUMBER | 傳回布林值 (Boolean),表示指定的運算式的型別是否為數字。 |
| IS_OBJECT | 傳回布林值,指示指定運算式的型別是否為 JSON 物件。 |
| IS_PRIMITIVE | 傳回布林值,可指出所指定之運算式的類型是否為基本類型 (字串、布林值、數值或 null)。 |
| IS_STRING | 傳回布林值,表示指定之運算式的型別為字串。 |
在路由條件中,支援下列字串函式:
| 功能 | 描述 |
|---|---|
| CONCAT(x, y, ...) | 傳回字串,該字串是串連兩個或多個字串值的結果。 |
| LENGTH(x) | 傳回指定字串運算式的字元數目。 |
| LOWER(x) | 傳回將大寫字元資料轉換成小寫之後的字串運算式。 |
| UPPER(x) | 傳回將小寫字元資料轉換成大寫之後的字串運算式。 |
| SUBSTRING(字串,起始 [, 長度]) | 傳回字串運算式的部分,從指定字元以零為起始的位置開始,直到指定的長度,或直到字串的結尾。 |
| INDEX_OF(字串,片段) | 傳回第一個指定的字串運算式中,第二個字串運算式第一次出現的開始位置;如果找不到字串,則為 -1。 |
| STARTS_WITH(x,y) | 傳回布林值,表示第一個字串運算式是否以第二個字串運算式開頭。 |
| ENDS_WITH(x, y) | 傳回布林值,表示第一個字串運算式是否以第二個字串運算式結尾。 |
| CONTAINS(x,y) | 傳回布林值,表示第一個字串運算式是否包含第二個字串運算式。 |
使用服務 SDK 的查詢範例
C# 範例
查詢功能由 Azure IoT 中樞 service SDK for .NET 在 RegistryManager 類別中外露。
以下是簡單查詢的範例︰
var query = registryManager.CreateQuery("SELECT * FROM devices", 100);
while (query.HasMoreResults)
{
var page = await query.GetNextAsTwinAsync();
foreach (var twin in page)
{
// do work on twin object
}
}
查詢物件會以 查詢結果分頁 區段中提及的參數具現化。 透過多次呼叫這些 GetNextAsTwinAsync 方法,可以取得多個頁面。
Node.js 範例
查詢功能由 Azure IoT 中樞 service SDK for Node.js 在 Registry 物件中揭露。
以下是簡單查詢的範例︰
var query = registry.createQuery('SELECT * FROM devices', 100);
var onResults = function(err, results) {
if (err) {
console.error('Failed to fetch the results: ' + err.message);
} else {
// Do something with the results
results.forEach(function(twin) {
console.log(twin.deviceId);
});
if (query.hasMoreResults) {
query.nextAsTwin(onResults);
}
}
};
query.nextAsTwin(onResults);
查詢物件會以 查詢結果分頁 區段中提及的參數具現化。 透過多次呼叫該 nextAsTwin 方法,可以取得多個頁面。
IoT 中樞裝置和模組對應項的查詢
裝置雙胞胎 和 模組雙胞胎 可以包含任意的 JSON 物件作為標籤和屬性。 IoT 中樞可讓您將裝置對應項和模組對應項,當作包含所有對應項資訊的單一 JSON 文件來進行查詢。
以下是一個 IoT 中樞裝置對應項的範例 (模組對應項的格式類似,只需加上 moduleId 參數):
{
"deviceId": "myDeviceId",
"etag": "AAAAAAAAAAc=",
"status": "enabled",
"statusUpdateTime": "0001-01-01T00:00:00",
"connectionState": "Disconnected",
"lastActivityTime": "0001-01-01T00:00:00",
"cloudToDeviceMessageCount": 0,
"authenticationType": "sas",
"x509Thumbprint": {
"primaryThumbprint": null,
"secondaryThumbprint": null
},
"version": 2,
"tags": {
"location": {
"region": "US",
"plant": "Redmond43"
}
},
"properties": {
"desired": {
"telemetryConfig": {
"configId": "db00ebf5-eeeb-42be-86a1-458cccb69e57",
"sendFrequencyInSecs": 300
},
"$metadata": {
...
},
"$version": 4
},
"reported": {
"connectivity": {
"type": "cellular"
},
"telemetryConfig": {
"configId": "db00ebf5-eeeb-42be-86a1-458cccb69e57",
"sendFrequencyInSecs": 300,
"status": "Success"
},
"$metadata": {
...
},
"$version": 7
}
}
}
裝置孿生查詢
IoT 中樞會將裝置對應項公開為名為 devices 的文件集合。 例如,最基本的查詢會取得整個裝置數位孿生集合:
SELECT * FROM devices
附註
Azure IoT SDK 支援大型結果的分頁。
你可以使用 SELECT 子句彙整查詢結果。 例如,以下查詢會計算物聯網集線器中裝置總數:
SELECT COUNT() as totalNumberOfDevices FROM devices
使用 WHERE 子句來過濾查詢結果。 例如,若要接收 location.region 標籤設為 US 的裝置對應項,請使用下列查詢:
SELECT * FROM devices
WHERE tags.location.region = 'US'
透過布林運算子和算術比較來建立複雜的 WHERE 子句。 例如,下列查詢會擷取位於美國且設定為每分鐘發送不到一次遙測的裝置對應項:
SELECT * FROM devices
WHERE tags.location.region = 'US'
AND properties.reported.telemetryConfig.sendFrequencyInSecs >= 60
您也可以搭配 IN 和 NIN (not in) 運算子來使用陣列常數。 例如,以下查詢會取得報告 WiFi 或有線連接的設備對偶:
SELECT * FROM devices
WHERE properties.reported.connectivity IN ['wired', 'wifi']
通常需要識別所有包含特定屬性的裝置雙胞胎。 IoT 中樞 支援功能 is_defined() 用於此目的。 例如,下列查詢會擷取定義 connectivity 屬性的裝置對應項:
SELECT * FROM devices
WHERE is_defined(properties.reported.connectivity)
完整過濾功能請參閱 WHERE 條款 章節。
同時也支援分組功能。 例如,以下查詢會回傳每個遙測配置狀態中的裝置數量:
SELECT properties.reported.telemetryConfig.status AS status,
COUNT() AS numberOfDevices
FROM devices
GROUP BY properties.reported.telemetryConfig.status
此分組查詢會回傳類似以下範例的結果:
[
{
"numberOfDevices": 3,
"status": "Success"
},
{
"numberOfDevices": 2,
"status": "Pending"
},
{
"numberOfDevices": 1,
"status": "Error"
}
]
在這個例子中,三台裝置報告成功設定,兩台仍在執行設定,另一台則報告錯誤。
投影查詢允許開發者只回傳他們關心的屬性。 例如,要取得所有已啟用且已停用的裝置的最後活動時間及裝置 ID,請使用以下查詢:
SELECT DeviceId, LastActivityTime FROM devices WHERE status = 'enabled' AND connectionState = 'Disconnected'
該查詢的結果如下範例:
[
{
"deviceId": "AZ3166Device",
"lastActivityTime": "2021-05-07T00:50:38.0543092Z"
}
]
模組孿生查詢
查詢模組雙胞胎類似於查詢裝置雙胞胎,但使用不同的集合/命名空間;不是從devices查詢,而是從devices.modules查詢。
SELECT * FROM devices.modules
我們不允許裝置與 devices.modules 集合之間進行連接。 如果你想跨裝置查詢模組雙胞,你需要根據標籤進行操作。 下列查詢會傳回所有裝置上具有掃描狀態的所有模組對應項:
SELECT * FROM devices.modules WHERE properties.reported.status = 'scanning'
下列查詢會傳回具有掃描狀態的模組對應項,但僅限於指定的裝置子集:
SELECT * FROM devices.modules
WHERE properties.reported.status = 'scanning'
AND deviceId IN ['device1', 'device2']
雙重查詢限制
Important
查詢結果最終會保持一致,且最多可容忍 30 分鐘的延遲。 在大多數情況下,雙查詢的結果通常會在幾秒鐘內回傳。 IoT 中樞會努力地為所有作業提供低延遲的服務。 但基於網路狀況和其他無法預測的因素,IoT 中樞無法保證特定延遲。
雙胞胎查詢的替代方案是利用 get twin REST API 以 ID 查詢個別裝置雙胞胎。 此 API 總是回傳最新值,且限速限制較高。 你可以直接發佈 REST API,或在 Azure IoT 中樞 Service SDK 中使用等效功能。
查詢表達式的最大長度可達 8,192 個字元。
目前,僅支援原始類型間的比較(不支援物件),例如 ... WHERE properties.desired.config = properties.reported.config 只有當這些屬性具有原始值時才支援。
在任何情境下,我們都建議不要依賴 Twin 查詢中的裝置身份屬性中的 lastActivityTime。 這個欄位無法保證能準確判斷裝置狀態。 相反地,應利用物聯網裝置生命週期事件來管理裝置狀態與活動。 關於如何在解決方案中使用IoT 中樞生命週期事件的資訊,請參見 透過事件網格觸發動作來回應IoT 中樞事件。
附註
避免對此操作的最大延遲做出任何假設。 請參閱 延遲解決方案 ,了解如何在考慮延遲的情況下建構解決方案。
IoT 中樞工作的查詢
工作提供一種在裝置集上執行作業的方法。 每個裝置對應項皆會在名為 jobs 的集合中,包含以該裝置為目標之工作的資訊。 IoT 中樞可讓您將工作當作包含所有對應項資訊的單一 JSON 文件來進行查詢。
這裡有一個物聯網集線中心裝置孿生的範例,它是名為 myJobId 的作業的一部分。
{
"deviceId": "myDeviceId",
"etag": "AAAAAAAAAAc=",
"tags": {
...
},
"properties": {
...
},
"jobs": [
{
"deviceId": "myDeviceId",
"jobId": "myJobId",
"jobType": "scheduleUpdateTwin",
"status": "completed",
"startTimeUtc": "2016-09-29T18:18:52.7418462",
"endTimeUtc": "2016-09-29T18:20:52.7418462",
"createdDateTimeUtc": "2016-09-29T18:18:56.7787107Z",
"lastUpdatedDateTimeUtc": "2016-09-29T18:18:56.8894408Z",
"outcome": {
"deviceMethodResponse": null
}
},
...
]
}
目前,這個集合在 IoT 中樞 查詢語言中可查詢為 devices.jobs。
Important
目前在查詢裝置對應項時,不會傳回 jobs 屬性。 也就是說,包含 FROM devices的查詢。 工作屬性只能透過查詢 FROM devices.jobs直接存取。
例如,以下查詢會回傳所有影響單一裝置的工作(過去與排程工作):
SELECT * FROM devices.jobs
WHERE devices.jobs.deviceId = 'myDeviceId'
請注意此查詢如何提供所傳回之各項工作針對特定裝置的狀態 (以及可能的直接方法回應)。
也可以對集合中 devices.jobs 的所有物件屬性設定任意布林條件來過濾。
例如,以下查詢會檢索 2016 年 9 月後為特定裝置建立的所有已完成的裝置雙重更新工作:
SELECT * FROM devices.jobs
WHERE devices.jobs.deviceId = 'myDeviceId'
AND devices.jobs.jobType = 'scheduleUpdateTwin'
AND devices.jobs.status = 'completed'
AND devices.jobs.createdTimeUtc > '2016-09-01'
您也可以擷取單一工作針對個別裝置的結果。
SELECT * FROM devices.jobs
WHERE devices.jobs.jobId = 'myJobId'
工作查詢限制
查詢表達式的最大長度可達 8,192 個字元。
目前,devices.jobs 的查詢不支援以下事項:
- 投影,因此僅能使用
SELECT *。 - 除了工作屬性之外,還參考裝置對應項的條件 (請參閱上一節)。
- 彙總,例如計數、平均和群組依據。
相關內容
- 了解如何使用 IoT 中樞訊息路由查詢語法,根據訊息屬性或訊息本文的方式來路由訊息。