デバイス ツイン、モジュール ツイン、ジョブ、メッセージ ルーティングの IoT Hub クエリ言語

IoT Hub には SQL に似た強力な言語が備わっており、デバイス ツインモジュール ツインジョブ、およびメッセージ ルーティングに関する情報を取得できます。 この記事で取り扱う内容は次のとおりです。

  • IoT Hub のクエリ言語の主な機能の説明
  • 言語の詳しい説明 メッセージ ルーティングにおけるクエリ言語の詳細については、メッセージ ルーティングでのクエリに関するページを参照してください。

具体的な例については、デバイスとモジュール ツインのクエリまたはジョブのクエリに関する記事をご覧ください。

Note

この記事で言及されている一部の機能 (cloud-to-device メッセージング、デバイス ツイン、デバイス管理など) は、IoT Hub の Standard レベルだけで使用することができます。 Basic および Standard または Free レベルの IoT Hub の詳細については、ソリューションに適した IoT Hub のレベルの選択に関するページを参照してください。

IoT Hub のクエリを実行する

Azure portal で直接 IoT ハブに対してクエリを実行できます。

  1. Azure Portal にサインインし、IoT Hub に移動します。
  2. ナビゲーション メニューの [デバイス管理] セクションから [クエリ] を選びます。
  3. テキスト ボックスにクエリを入力して、[クエリの実行] を選びます。

また、Azure IoT サービス SDK とサービス API を使って、アプリケーション内でクエリを実行することもできます。

IoT Hub のクエリを実装するコードの例については、「サービス SDK を使用するクエリの例」セクションをご覧ください。

SDK のリファレンス ページとサンプルへのリンクについては、Azure IoT SDK に関する記事をご覧ください。

IoT Hub クエリの基礎

IoT Hub のすべてのクエリは、SELECT 句と FROM 句、およびオプションの WHERE 句と GROUP BY で構成されます。

クエリは JSON ドキュメントのコレクション (デバイス ツインなど) で実行されます。 FROM 句は、反復対象のドキュメント コレクション (devicesdevices.modules、または devices.jobs) を示します。

次に、WHERE 句でフィルター処理が適用されます。 集計により、この手順の結果は GROUP BY 句の指定に従ってグループ化されます。 グループごとに、SELECT 句で指定された行が生成されます。

SELECT <select_list>
  FROM <from_specification>
  [WHERE <filter_condition>]
  [GROUP BY <group_specification>]

SELECT 句

SELECT <select_list> 句は、すべての IoT Hub クエリで必要です。 クエリで取得する値を指定します。 これは、新しい 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 クエリで必要です。 3 つの値のいずれかである必要があります。

  • デバイス ツインのクエリを実行するための devices
  • モジュール ツインのクエリを実行するための devices.modules
  • デバイスごとのジョブの詳細のクエリを実行するための devices.jobs

次に例を示します。

  • すべてのデバイス ツインを取得する

    SELECT * FROM devices
    

WHERE 句

WHERE <filter_condition> 句はオプションです。 WHERE 句は、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 と見なされます。 このルールには、null未定義、任意のオブジェクトまたは配列インスタンス、任意の文字列、およびブール値の 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>]+ ']'

式の構文で使われている各シンボルの意味については、次の表をご覧ください。

Symbol 定義
attribute_name FROM コレクションの JSON ドキュメントのプロパティ。
binary_operator 演算子」セクションに記載されている 2 項演算子。
function_name 関数」セクションに記載されている関数。
decimal_literal 10 進表記で表される浮動小数点数。
hexadecimal_literal 文字列 '0x' の後に 16 進数の文字列を続けて表された数値。
string_literal 0 個以上の Unicode 文字のシーケンスまたはエスケープ シーケンスによって表される Unicode 文字列。 文字列リテラルは、単一引用符または二重引用符で囲みます。 使用できるエスケープ: 4 つの 16 進数字によって定義された Unicode 文字の \'\"\\\uXXXX

オペレーター

次の演算子がサポートされています。

ファミリ オペレーター
算術 +, -, *, /, %
論理 AND、OR、NOT
比較 =、!=、<、>、<=、>=、<>

関数

ツインとジョブのクエリにおいて、サポートされている唯一の関数は次のとおりです。

機能 説明
IS_DEFINED(property) プロパティに値が代入されているかどうかを示すブール値を返します (null を含む)。

ルートの条件では、次の計算関数がサポートされています。

機能 説明
ABS(x) 指定された数値式の絶対値 (正の値) を返します。
EXP(x) 指定された数値式の指数値を返します (e^x)。
POWER(x,y) 指定されたべき乗の指定された式の値を返します (x^y)。
SQUARE(x) 指定された数値の 2 乗を返します。
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, …) 2 つ以上の文字列値を連結した結果である文字列を返します。
LENGTH(x) 指定された文字列式の文字数を返します。
LOWER(x) 文字列式の大文字データを小文字に変換して返します。
UPPER(x) 文字列式の小文字データを大文字に変換して返します。
SUBSTRING(string, start [, length]) 指定された文字のゼロベースの位置で始まる文字列式の一部を返し、指定された長さまたは文字列の末尾まで続きます。
INDEX_OF(string, fragment) 1 つ目に指定された文字列式内で、2 つ目の文字列式が最初に出現する箇所の開始位置を返します。文字列が見つからない場合は -1 を返します。
STARTSWITH(x, y) 1 つ目の文字列式が 2 つ目の文字列で始まっているかどうかを示すブール値を返します。
ENDSWITH(x, y) 1 つ目の文字列式が 2 つ目の文字列で終了しているかどうかを示すブール値を返します。
CONTAINS(x,y) 1 つ目の文字列式に 2 つ目の文字列式が含まれているかどうかを示すブール値を返します。

サービス SDK を使用したクエリの例

C# の例

クエリ機能は RegistryManager クラスの C# サービス SDK で公開されます。

簡単なクエリの例を次に示します。

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 の使用例

クエリ機能は Registry オブジェクトの Azure IoT service SDK for Node.js で公開されます。

簡単なクエリの例を次に示します。

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 メソッドを複数回呼び出すと、複数のページが取得されます。

次のステップ