裝置與模組對應項、作業和訊息路由的 IoT 中樞查詢語言

IoT 中樞提供功能強大、類似 SQL 的語言,以擷取有關裝置對應項模組對應項作業訊息路由的資訊。 本文提供︰

  • IoT 中樞查詢語言主要功能的簡介,以及
  • 語言的詳細說明。 如需訊息路由查詢語言的詳細資訊,請參閱訊息路由中的查詢

如需特定範例,請參閱裝置和模組對應項的查詢作業的查詢

注意

本文中提及的某些功能 (例如雲端對裝置傳訊、裝置對應項和裝置管理) 僅適用於 IoT 中樞的標準層。 如需基本和標準/免費IoT 中樞層的詳細資訊,請參閱為您的解決方案選擇正確的IoT 中樞層

執行 IoT 中樞查詢

您可以直接在 Azure 入口網站中對 IoT 中樞執行查詢。

  1. 登入 Azure 入口網站,然後瀏覽至 IoT 中樞。
  2. 從導覽功能表的 [裝置管理] 區段中選取 [查詢]。
  3. 在文字方塊中輸入查詢,並選取 [執行查詢]

您也可以使用 Azure IoT 服務 SDK 和服務 API,在應用程式中執行查詢。

如需實作 IoT 中樞查詢的範例程式碼,請參閱使用服務 SDK 的查詢範例一節。

如需 SDK 參考頁面和範例的連結,請參閱 Azure IoT SDK

IoT 中樞查詢的基本概念

每個「IoT 中樞」查詢都包含 SELECT 和 FROM 子句,以及選擇性的 WHERE 和 GROUP BY 子句。

查詢都會在 JSON 文件的集合上執行,例如裝置對應項。 FROM 子句會指出要在其上反覆運算的文件集合 (devicesdevices.modulesdevices.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 子句

每個 IoT 中樞查詢都需要 FROM <from_specification> 子句。 必須是下列三個值中的其中一個:

  • devices,用來查詢裝置對應項
  • devices.modules,用來查詢模組對應項
  • devices.jobs,用來查詢每個裝置的作業詳細資料

例如:

  • 擷取所有裝置對應項

    SELECT * FROM devices
    

WHERE 子句

WHERE <filter_condition> 子句是選擇性的。 它會指定一或多個條件,而且 FROM 集合中的 JSON 文件必須滿足這些條件,才能納入為結果的一部分。 任何 JSON 文件都必須將指定的條件評估為 "true",才能併入結果。

例如:

  • 擷取以特定裝置為目標的所有作業

    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 一詞目前被視為查詢中的特殊關鍵字。 萬一您使用 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 文件的任何屬性。

查詢結果分頁

查詢物件會以 小於等於 100 筆記錄的最大頁面大小具現化。 若要取得多個頁面,請在 Node.js SDK 上呼叫 nextAsTwin 或 .Net SDK 方法上的 GetNextAsTwinAsync 多次。 查詢物件可以公開多個 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>]+ ']'

若要了解運算式語法中每個符號所代表的意義,請參閱下表:

符號 定義
attribute_name FROM 集合中 JSON 文件的任何屬性。
binary_operator 運算子一節中所列的任何二元運算子。
function_name 函式一節中所列的任何函式。
decimal_literal 以小數點標記法表示的浮點數。
hexadecimal_literal 以字串 '0x' 後面接著十六進位數字的字串所表示的數字。
string_literal 由零個或多個 Unicode 字元序列或逸出序列所表示的 Unicode 字串。 字串常值會以單引號或雙引號括起來。 允許的逸出︰\'\"\\\uXXXX (適用於由四個十六進位數字所定義的 Unicode 字元)。

運算子

支援下列運算子:

系列 運算子
算術 +, -, *, /, %
邏輯 AND、OR、NOT
比較 =、!=、<、>、<=、>=、<>

函式

查詢對應項和作業時唯一支援的函式為:

函式 描述
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 傳回布林值,表示指定之運算式的類型為數字。
IS_OBJECT 傳回布林值,表示指定之運算式的類型為 JSON 物件。
IS_PRIMITIVE 傳回布林值,可指出所指定之運算式的類型是否為基本類型 (字串、布林值、數值或 null)。
IS_STRING 傳回布林值,表示指定之運算式的類型為字串。

在路由條件中,支援下列字串函式:

函式 描述
CONCAT(x, y, …) 傳回字串,該字串是串連兩個或多個字串值的結果。
LENGTH(x) 傳回指定字串運算式的字元數目。
LOWER(x) 傳回將大寫字元資料轉換成小寫之後的字串運算式。
UPPER(x) 傳回將小寫字元資料轉換成大寫之後的字串運算式。
SUBSTRING(string, start [, length]) 傳回字串運算式的部分,從指定字元以零為起始的位置開始,直到指定的長度,或直到字串的結尾。
INDEX_OF(string, fragment) 傳回第一個指定的字串運算式中,第二個字串運算式第一次出現的開始位置;如果找不到字串,則為 -1。
STARTSWITH (x, y) 傳回布林值,表示第一個字串運算式是否以第二個字串運算式開頭。
ENDSWITH (x, y) 傳回布林值,表示第一個字串運算式是否以第二個字串運算式結尾。
CONTAINS(x,y) 傳回布林值,表示第一個字串運算式是否包含第二個字串運算式。

使用服務 SDK 查詢範例

C# 範例

查詢功能由 C# 服務 SDKRegistryManager 類別中公開。

以下是簡單查詢的範例︰

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 範例

查詢功能由適用於 Node.js 的 Azure IoT 服務 SDKRegistry 物件中公開。

以下是簡單查詢的範例︰

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 方法多次來擷取多個頁面。

下一步