Interroger le graphe de jumeaux Azure Digital Twins

Cet article fournit des exemples de requête et des instructions sur l’utilisation du langage de requête Azure Digital Twins pour interroger votre graphe de jumeaux afin d’obtenir des informations. (Pour une présentation du langage de requête, consultez Langage de requête.)

L’article contient des exemples de requête qui illustrent la structure du langage de requête et les opérations de requête courantes pour des jumeaux numériques. Il décrit également comment exécuter vos requêtes une fois que vous les avez écrites, à l’aide de l’API de requête Azure Digital Twins ou d’un KIT de développement logiciel (SDK).

Notes

Si vous exécutez les exemples de requête ci-dessous avec un appel d’API ou de SDK, vous devez condenser le texte de la requête sur une seule ligne.

Documentation de référence

Les informations de référence sur le langage de requête se trouvent sous Informations de référence dans la table des matières de gauche de la documentation Azure Digital Twins. Vous pouvez également accéder directement aux sections de référence en utilisant les liens ci-dessous :

Montrer tous les jumeaux numériques

Voici la requête de base qui retourne la liste de tous les jumeaux numériques dans l’instance :

SELECT * FROM DIGITALTWINS

Requête par propriété

Obtenir les jumeaux numériques d’après leurs propriétés (y compris l’ID et les métadonnées) :

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

Comme le montre la requête ci-dessus, l’ID d’un jumeau numérique est interrogé à l’aide du champ de métadonnées $dtId.

Conseil

Si vous utilisez Cloud Shell pour exécuter une requête avec des champs de métadonnées qui commencent par $, vous devez placer le $ dans une séquence d’échappement avec une barre oblique inverse pour signaler à Cloud Shell qu’il ne s’agit pas d’une variable et qu’il doit être consommé comme littéral dans le texte de la requête.

Vous pouvez également obtenir des jumeaux en fonction de la définition ou non d’une certaine propriété. Voici une requête qui récupère les jumeaux dont la propriété Location a été définie :

SELECT *​ FROM DIGITALTWINS WHERE IS_DEFINED(Location)

Cette requête vous permet d’obtenir des jumeaux par le biais de leurs propriétés tag, comme décrit dans Ajouter des étiquettes à des jumeaux numériques. Voici une requête qui récupère tous les jumeaux étiquetés avec red :

SELECT * FROM DIGITALTWINS WHERE IS_DEFINED(tags.red)

Vous pouvez également obtenir des jumeaux selon le type d’une propriété. Voici une requête qui récupère les jumeaux dont la propriété Temperature est un nombre :

SELECT * FROM DIGITALTWINS​ T WHERE IS_NUMBER(T.Temperature)

Propriétés du mappage de requêtes

Si une propriété est du type Mapcomplexe , vous pouvez utiliser les clés de mappage et les valeurs directement dans la requête, comme suit :

SELECT * FROM DIGITALTWINS​ T WHERE T.<propertyName>.<mapKey> = '<mapValue>'

Si la clé de carte commence par un caractère numérique, vous devez encapsuler la clé entre crochets doubles ([[<mapKey>]]) pour l’échapper dans la requête, comme dans la stratégie d’interrogation avec des mots clés réservés.

Requête par modèle

L’opérateur IS_OF_MODEL peut être utilisé pour filtrer en fonction du modèle de jumeau.

Il prend en compte l’héritage et le contrôle de version du modèle et prend la valeur true pour un jumeau donné si le jumeau remplit l’une des conditions suivantes :

  • Le jumeau implémente directement le modèle fourni à IS_OF_MODEL(), et le numéro de version du modèle sur le jumeau est supérieur ou égal au numéro de version du modèle fourni.
  • Le jumeau implémente un modèle qui étend le modèle fourni à IS_OF_MODEL(), et le numéro de version du modèle étendu du jumeau est supérieur ou égal au numéro de version du modèle fourni.

Par exemple, si vous interrogez les jumeaux du modèle dtmi:example:widget;4, la requête renvoie tous les jumeaux basés sur la version 4 ou ultérieure du modèle widget, ainsi que les jumeaux basés sur la version 4 ou ultérieure de tous les modèles qui héritent du widget.

IS_OF_MODEL peut prendre plusieurs paramètres différents, et le reste de cette section est dédié à ses différentes options de surcharge.

L’utilisation la plus simple de IS_OF_MODEL ne prend qu’un paramètre twinTypeName : IS_OF_MODEL(twinTypeName). Voici un exemple de requête qui transmet une valeur dans ce paramètre :

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

Pour spécifier une collection de jumeaux à rechercher lorsqu’il en existe plusieurs (par exemple, lorsqu’un JOIN est utilisé), ajoutez le paramètre twinCollection : IS_OF_MODEL(twinCollection, twinTypeName). Voici un exemple de requête qui transmet une valeur dans ce paramètre :

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

Pour effectuer une correspondance exacte, ajoutez le paramètre exact : IS_OF_MODEL(twinTypeName, exact). Voici un exemple de requête qui transmet une valeur dans ce paramètre :

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

Vous pouvez également passer les trois arguments ensemble : IS_OF_MODEL(twinCollection, twinTypeName, exact). Voici un exemple de requête spécifiant une valeur pour les trois paramètres :

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

Requête par relation

Lorsque vous effectuez une interrogation basée sur les relations des jumeaux numériques, sachez que le langage du magasin de requêtes d’Azure Digital Twins présente une syntaxe spéciale.

Les relations sont tirées (pull) puis ajoutées à l’étendue de la requête dans la clause FROM. Contrairement aux langages de type SQL « classiques », chaque expression de cette clause FROM n’est pas une table. La clause FROM exprime plutôt un parcours des relations entre les entités. Pour parcourir les relations, Azure Digital Twins utilise une version personnalisée de JOIN.

Rappelez-vous qu’avec les capacités de modèle d’Azure Digital Twins, les relations n’existent pas indépendamment des jumeaux, ce qui signifie que les relations ici ne peuvent être interrogées indépendamment et doivent être liées à un jumeau. Pour refléter ce fait, le mot clé RELATED est utilisé dans la clause JOIN pour extraire l’ensemble d’un certain type de relation provenant de la collection de jumeaux. La requête doit ensuite filtrer dans la clause WHERE pour indiquer le(s) jumeau(x) spécifique(s) à utiliser dans la requête de relation (à l’aide des valeurs $dtId des jumeaux).

Les sections suivantes fournissent des exemples.

Requête de relation de base

Voici un exemple de requête basée sur les relations. Cet extrait de code sélectionne tous les jumeaux numériques dont la propriété ID a la valeur ABC, ainsi que tous les jumeaux numériques associés à ces jumeaux via une relation contains.

SELECT T, CT
FROM DIGITALTWINS T
JOIN CT RELATED T.contains
WHERE T.$dtId = 'ABC'

Le type de relation (contains dans l’exemple ci-dessus) est indiqué par le champ name de la relation dans sa définition DTDL.

Notes

Le développeur n’a pas besoin de mettre en corrélation ce JOIN avec une valeur de clé dans la clause WHERE (ni de spécifier une valeur de clé inline avec la définition JOIN). Cette corrélation est calculée automatiquement par le système, puisque les propriétés de relation identifient l’entité cible.

Interroger selon la source ou la cible d’une relation

Vous pouvez utiliser la structure de requête de relation pour identifier un jumeau numérique qui est la source ou la cible d’une relation.

Par exemple, vous pouvez commencer avec un jumeau source et suivre ses relations pour trouver les jumeaux cibles des relations. Voici un exemple de requête qui recherche les jumeaux cibles des relations de feeds provenant du jumeau source du jumeau.

SELECT target 
FROM DIGITALTWINS source 
JOIN target RELATED source.feeds 
WHERE source.$dtId = 'source-twin'

Vous pouvez également commencer avec la cible de la relation et effectuer le suivi de la relation pour retrouver le jumeau source. Voici un exemple de requête qui permet de trouver le jumeau source d’une relation de feeds avec le jumeau cible du jumeau.

SELECT source 
FROM DIGITALTWINS source 
JOIN target RELATED source.feeds 
WHERE target.$dtId = 'target-twin'

Interroger les propriétés d’une relation

De même qu’il est possible de décrire les propriétés des jumeaux numériques via DTDL, les relations peuvent elles aussi avoir des propriétés. Vous pouvez interroger les jumeaux selon les propriétés de leurs relations. Le langage d’Azure Digital Twins permet le filtrage et la projection des relations, en affectant un alias à la relation dans la clause JOIN.

Prenons l’exemple d’une relation servicedBy qui comprendrait une propriété reportedCondition. Dans la requête ci-dessous, cette relation se voit attribuer l’alias R afin de référencer sa propriété.

SELECT T, SBT, R
FROM DIGITALTWINS T
JOIN SBT RELATED T.servicedBy R
WHERE T.$dtId = 'ABC'
AND R.reportedCondition = 'clean'

Dans l’exemple ci-dessus, notez que reportedCondition est une propriété de la relation servicedBy (et non d’un jumeau numérique ayant une relation servicedBy).

Interroger avec plusieurs clauses JOIN

Jusqu’à cinq clauses JOIN sont prises en charge dans une même requête, ce qui vous permet de traverser plusieurs niveaux de relations à la fois.

Pour effectuer une requête à plusieurs niveaux de la relation, utilisez une instruction FROM suivie de N instructions JOIN, où les instructions JOIN expriment les relations basées sur le résultat d’une instruction FROM ou JOIN précédente.

Voici un exemple de requête à plusieurs JOIN, qui permet d’obtenir toutes les ampoules contenues dans les panneaux lumineux des pièces 1 et 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']

Compter les éléments

Vous pouvez compter le nombre d’éléments dans un jeu de résultats à l’aide de la clause Select COUNT :

SELECT COUNT()
FROM DIGITALTWINS

Ajoutez une clause WHERE pour compter le nombre d’éléments qui répondent à un certain critère. Voici quelques exemples de comptage avec un filtre appliqué en fonction du type de modèle de jumeau (pour plus d’informations sur cette syntaxe, consultez Requête par modèle ci-dessous) :

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

Vous pouvez également utiliser COUNT avec la clause JOIN . Voici une requête qui compte toutes les ampoules contenues dans les panneaux lumineux des salles 1 et 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']

Filtrer les résultats : sélectionner les meilleurs éléments

Vous pouvez sélectionner les meilleurs éléments dans une requête à l’aide de la clause Select TOP.

SELECT TOP (5)
FROM DIGITALTWINS
WHERE ...

Filtrer les résultats : spécifier un jeu de retour avec des projections

En utilisant des projections dans l’instruction SELECT, vous pouvez choisir les colonnes qui sont renvoyées par une requête. La projection est désormais prise en charge pour les propriétés primitives et complexes. Pour plus d’informations sur les projections avec Azure Digital Twins, consultez la documentation de référence sur la clause SELECT.

Voici un exemple de requête qui utilise la projection pour retourner les jumeaux et les relations. La requête ci-dessous projette Consumer, Factory et Edge dans un scénario où une Factory avec l’ID ABC est liée au Consumer via une relation Factory.customer, et cette relation est présentée en tant que Edge.

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

Vous pouvez également utiliser la projection pour retourner une propriété d’un jumeau. La requête suivante projette la propriété Name des Consumers associés à la Factory avec l’ID ABC via une relation de Factory.customer.

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

Vous pouvez également utiliser la projection pour retourner une propriété d’une relation. Comme dans l’exemple précédent, la requête suivante projette la propriété Name des Consumers associés à la Factory avec un ID ABC via une relation de Factory.customer. Elle retourne maintenant également deux propriétés de cette relation : prop1 et prop2. Pour ce faire, elle nomme la relation Edge et collecte ses propriétés.

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

Vous pouvez également utiliser des alias pour simplifier les requêtes avec projection.

La requête suivante effectue les mêmes opérations que l’exemple précédent, mais elle associe les noms de propriété à consumerName, first, second et 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'

Voici une requête similaire qui interroge le même jeu que ci-dessus, mais projette uniquement la propriété Consumer.name en tant que consumerName et projette la fabrique complète en tant que jumeau.

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

Créer des requêtes efficaces avec l’opérateur IN

Vous pouvez réduire considérablement le nombre de requêtes dont vous avez besoin en générant un tableau de jumeaux et en l’interrogeant à l’aide de l’opérateur IN.

Par exemple, imaginons un scénario dans lequel des immeubles comprennent des étages, et ces étages comprennent des pièces. Pour rechercher des salles chauffées dans un immeuble, vous pouvez suivre ces étapes.

  1. Recherchez les étages de l’immeuble en fonction de la relation contains.

    SELECT Floor
    FROM DIGITALTWINS Building
    JOIN Floor RELATED Building.contains
    WHERE Building.$dtId = @buildingId
    
  2. Pour trouver des pièces, au lieu de prendre les étages un par un et d’exécuter une requête JOIN afin de rechercher les pièces de chacun d’eux, vous pouvez interroger une collection d’étages de l’immeuble (nommée Floor dans la requête ci-dessous).

    Dans l’application cliente :

    var floors = "['floor1','floor2', ..'floorn']"; 
    

    Dans la requête :

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

Autres exemples de requêtes composées

Vous pouvez combiner un des types de requête ci-dessus avec des opérateurs de combinaison pour inclure plus de détails dans une seule requête. Voici quelques autres exemples de requêtes composées qui interrogent plusieurs types de descripteur de jumeau à la fois.

  • Parmi les appareils qui équipent Room 123 (la salle 123), retournez les appareils MxChip qui remplissent le rôle d’Operator (opérateur)
    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'
    
  • Récupérez les jumeaux qui présentent une relation nommée Contains (Contient) avec un autre jumeau dont l’ID est id1
    SELECT Room
    FROM DIGITALTWINS Room
    JOIN Thermostat RELATED Room.Contains
    WHERE Thermostat.$dtId = 'id1'
    
  • Récupérez toutes les salles de ce modèle de salle qui sont contenues dans floor11 (l’étage11)
    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')
    

Exécuter des requêtes avec l’API

Une fois que vous avez choisi une chaîne de requête, exécutez-la en appelant l’API de requête.

Vous pouvez appeler l’API directement ou utiliser l’un des SDK disponibles pour Azure Digital Twins.

L’extrait de code suivant illustre l’appel au SDK .NET (C#) à partir de l’application cliente :

// Run a query for all twins   
string query = "SELECT * FROM DIGITALTWINS";
AsyncPageable<BasicDigitalTwin> result = client.QueryAsync<BasicDigitalTwin>(query);

La requête utilisée dans cet appel retourne une liste de jumeaux numériques, que l’exemple ci-dessus représente avec des objets BasicDigitalTwin. Le type de retour de vos données pour chaque requête dépend des termes que vous spécifiez avec l’ instruction SELECT :

  • Les requêtes qui commencent par SELECT * FROM ... retournent une liste de jumeaux numériques (qui peuvent être sérialisés sous la forme d’objets BasicDigitalTwin ou d’autres types de jumeaux numériques personnalisés que vous avez peut-être créés).
  • Les requêtes qui commencent au format SELECT <A>, <B>, <C> FROM ... retournent un dictionnaire avec des clés <A>, <B> et <C>.
  • D’autres formats d’instructions SELECT peuvent être élaborés pour retourner des données personnalisées. Vous pouvez envisager de créer vos propres classes pour gérer des jeux de résultats personnalisés.

Requête avec pagination

Les appels de requête prennent en charge la pagination. Voici un exemple complet qui utilise BasicDigitalTwin en tant que type de résultat de requête avec gestion des erreurs et pagination :

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;
}

Étapes suivantes

Découvrez les API et SDK Azure Digital Twins, y compris l’API de requête qui est utilisée pour exécuter les requêtes de cet article.