Azure Digital Twins ツイン グラフに対してクエリを実行する

この記事では、クエリの例と、Azure Digital Twins クエリ言語 を使用して ツイン グラフで情報をクエリする手順について説明します。 (クエリ言語の概要については、クエリ言語に関する記事を参照してください。)

この記事では、デジタル ツインのクエリ言語の構造および共通のクエリ操作を示すサンプル クエリについて説明します。 また、Azure Digital Twins の Query API または SDK を使用して、クエリを作成した後にそれらを実行する方法について説明します。

注意

次のサンプル クエリを、API または SDK の呼び出しで実行している場合は、クエリ テキストを 1 行にまとめる必要があります。

リファレンス ドキュメント

クエリ言語リファレンス は、Azure Digital Twins ドキュメントの左側の目次の「リファレンス」の下にあります。 次のリンクを使用して、リファレンス セクションに直接アクセスすることもできます。

すべてのデジタル ツインを表示する

次に示すのは、インスタンス内のすべてのデジタル ツインの一覧を返す基本的なクエリです。

SELECT * FROM DIGITALTWINS

プロパティで照会

プロパティ (ID とメタデータを含む) を指定してデジタル ツインを取得します。

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

上記のクエリに示されているように、デジタル ツインの ID は、メタデータ フィールド $dtId を使用してクエリが実行されます。

ヒント

Cloud Shell を使用して、$ で始まるメタデータ フィールドでクエリを実行する場合は、バッククォートで $ をエスケープして、それが変数ではなく、クエリ テキスト内のリテラルとして使用する必要があることを Cloud Shell に通知する必要があります。

特定のプロパティが定義されているかどうか に基づいて Twins を取得することもできます。 次は、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>'

モデルでクエリを実行する

IS_OF_MODEL 演算子を使用すると、ツインのモデルに基づいてフィルター処理できます。

継承 とモデルの バージョン管理を調べた上で、指定されたツインが次のいずれかの条件を満たしている場合に、そのツインに対して true として評価されます。

  • IS_OF_MODEL() に指定されたモデルがツインに直接実装され、ツイン上のモデルのバージョン番号が、指定されたモデルのバージョン番号 "以上" である。
  • IS_OF_MODEL() に指定されたモデルを "拡張する" モデルがツインに実装され、ツインの拡張モデルのバージョン番号が、指定されたモデルのバージョン番号 "以上" である。

したがって、たとえば、モデル dtmi:example:widget;4 のツインに対してクエリを実行した場合、このクエリから返されるのは、バージョン 4 以上ウィジェット モデルに基づくすべてのツインと、さらに バージョン 4 以上 の、ウィジェットから継承した任意のモデル に基づくツインとなります。

IS_OF_MODEL にはいくつかの異なるパラメーターを指定することができます。このセクションの残りの部分では、その各種のオーバーロード オプションのみについて説明します。

IS_OF_MODEL の最も簡単な使用法では、IS_OF_MODEL(twinTypeName) のように twinTypeName パラメーターのみを受け取ります。 このパラメーターで値を渡すクエリの例を次に示します。

SELECT * FROM DIGITALTWINS WHERE IS_OF_MODEL('dtmi:example:thing;1')

(JOIN が使用されている場合のように) 複数のツイン コレクションがある場合に検索対象を指定するには、IS_OF_MODEL(twinCollection, twinTypeName) のように twinCollection パラメーターを追加します。 このパラメーターに値を追加するクエリの例を次に示します。

SELECT * FROM DIGITALTWINS DT WHERE IS_OF_MODEL(DT, 'dtmi:example:thing;1')

完全一致を行うには、IS_OF_MODEL(twinTypeName, exact) のように exact パラメーターを追加します。 このパラメーターに値を追加するクエリの例を次に示します。

SELECT * FROM DIGITALTWINS WHERE IS_OF_MODEL('dtmi:example:thing;1', exact)

また、IS_OF_MODEL(twinCollection, twinTypeName, exact) のように 3 つの引数すべてを渡すこともできます。 3 つのパラメーターすべての値を指定するクエリの例を次に示します。

SELECT * FROM DIGITALTWINS DT WHERE IS_OF_MODEL(DT, 'dtmi:example:thing;1', exact)

リレーションシップによるクエリ

デジタル ツインの リレーションシップ に基づいてクエリを実行する場合、Azure Digital Twins クエリ言語には特殊な構文があります。

リレーションシップは FROM 句のクエリ スコープにプルされます。 "従来の" SQL 型言語とは異なり、FROM 句の各式はテーブルではありません。そうではなく、FROM 句は、エンティティ間のリレーションシップのトラバーサルを表します。 リレーションシップをトラバーサルするために、Azure Digital Twins ではカスタム バージョンの JOIN を使用します。

Azure Digital Twins モデルの機能を使用すると、リレーションシップがツインとは無関係に存在しないことを思い出してください。これは、リレーションシップを個別に照会することができず、ツインに関連付けられている必要があることを意味します。 この事実を反映するために、キーワード RELATEDJOIN 句に使用して、ツイン コレクションからの特定の種類のリレーションシップのセットを取得します。 次に、クエリでは、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 Digital Twins ストア言語を使用すると、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'

上記の例では、reportedConditionservicedBy リレーションシップ自体のプロパティであることに注意してください (servicedBy リレーションシップを持つ何らかのデジタル ツインではありません)。

複数の JOIN を使用したクエリ

1 つのクエリで最大 5 つの JOIN がサポートされているため、複数レベルのリレーションシップを一度に走査できます。

複数レベルのリレーションシップをクエリするには、1 つの FROM ステートメントに続けて N 個の 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

また、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 句を使用して、1 つのクエリで複数の "上位" 項目を選択できます。

SELECT TOP (5)
FROM DIGITALTWINS
WHERE ...

結果のフィルター処理: プロジェクションを使用して戻り値のセットを指定する

SELECT ステートメントでプロジェクションを使用すると、クエリによって返される列を選択できます。 プロジェクションは、プリミティブおよび複合プロパティの両方でサポートされるようになりました。 Azure Digital Twins によるプロジェクションの詳細については、SELECT 句のリファレンス ドキュメントを参照してください。

プロジェクションを使用してツインとリレーションシップを返すクエリの例を次に示します。 次のクエリでは、ID が "ABC" の "Factory" が "Factory.customer" のリレーションシップを介して "Consumer" と関連付けられており、そのリレーションシップが "Edge" として表されるシナリオから、"Consumer"、"Factory"、"Edge" がプロジェクションされています。

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

また、プロジェクションを使用してツインのプロパティを返すこともできます。 以下のクエリでは、"Factory.customer" のリレーションシップを介して、ID が "ABC" の "Factory" に関連付けられている "Consumers" の "Name" プロパティがプロジェクションされています。

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

また、プロジェクションを使用してリレーションシップのプロパティを返すこともできます。 前述の例と同様に、以下のクエリでは、"Factory.customer" のリレーションシップを介して、ID が "ABC" の "Factory" に関連付けられている "Consumers" の "Name" プロパティがプロジェクションされていますが、今回は、そのリレーションシップの 2 つのプロパティである 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'

また、別名を使用して、プロジェクションによるクエリを簡略化することもできます。

次のクエリを実行すると、前述の例と同じ操作が行われますが、プロパティ名には別名の consumerNamefirstsecond、および 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 演算子を使用してクエリを実行します。

たとえば、"Buildings"(建物) に "Floors" (フロア) が含まれ、"Floors" に "Rooms" (部屋) が含まれるシナリオを考えてみます。 建物内の暑い部屋を見つけるには、1 つの方法として、次の手順に従います。

  1. contains のリレーションシップに基づいて、建物内のフロアを見つけます。

    SELECT Floor
    FROM DIGITALTWINS Building
    JOIN Floor RELATED Building.contains
    WHERE Building.$dtId = @buildingId
    
  2. 部屋を見つけるには、フロアを 1 つずつ検討し、JOIN クエリを実行してそれぞれの部屋を見つけるのではなく、建物内のフロアのコレクション (以下のクエリでは Floor という名前) を使用してクエリを実行することができます。

    クライアント アプリ:

    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')
    

その他の複合クエリの例

結合演算子を使用して上記のクエリ タイプを 組み合わせ、1 つのクエリに含める詳細を増やすことができます。 次に、複数のツイン記述子の種類に対して一度にクエリを実行する複合クエリのその他の例をいくつか挙げます。

  • Room 123 に与えられているデバイスの中から、Operator の役割を担う 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'
    
  • ID が id1 の別のツインとの間に Contains という名前のリレーションシップがあるツインを取得します
    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 を使用してクエリを実行する

クエリ文字列を決定したら、Query API を呼び出して実行します。

API を直接呼び出すか、Azure Digital Twins で使用可能な 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;
}

次のステップ

この記事のクエリの実行に使用される Query API を含め、詳細については、Azure Digital Twins API と SDK に関する記事を参照してください。