Langage de requête IoT Hub pour les jumeaux d’appareil et de module, les travaux et le routage des messages

IoT Hub fournit un puissant langage de type SQL pour récupérer des informations concernant les jumeaux d’appareil, les jumeaux de module, les travaux et le routage de messages. Cet article présente les éléments suivants :

  • Une introduction aux principales fonctionnalités du langage de requête d’IoT Hub
  • Une description détaillée du langage Pour plus d’informations sur le langage de requête pour le routage des messages, consultez Requêtes dans le routage des messages.

Pour obtenir des exemples spécifiques, consultez Requêtes pour les jumeaux de module et d’appareil ou Requêtes pour les travaux.

Notes

Certaines des fonctionnalités mentionnées dans cet article, comme la messagerie cloud-à-appareil, les jumeaux d’appareil et la gestion des appareils, sont disponibles uniquement dans le niveau Standard d’IoT Hub. Pour plus d’informations sur les niveaux de base et standard/gratuit d’IoT Hub, consultez Choisir le niveau IoT Hub correspondant à votre solution.

Exécuter des requêtes IoT Hub

Vous pouvez exécuter des requêtes sur votre hub IoT directement dans le portail Azure.

  1. Connectez-vous au portail Azure et accédez à votre IoT Hub.
  2. Sélectionnez Requêtes dans la section Gestion des appareils du menu de navigation.
  3. Entrez votre requête dans la zone de texte, puis sélectionnez Exécuter la requête.

Vous pouvez également exécuter des requêtes au sein de vos applications à l’aide du kit Azure IoT service SDK et des API de service.

Par du code exemple implémentant des requêtes IoT Hub, consultez la section Exemples de requête avec le kit SDK du service.

Pour obtenir des liens vers des pages de référence et des exemples du SDK, consultez SDK Azure IoT.

Principes de base d’une requête IoT Hub

Chaque requête IoT Hub se compose de clauses SELECT et FROM, avec des clauses WHERE et GROUP BY facultatives.

Les requêtes sont exécutées sur un regroupement de documents JSON, par exemple des jumeaux d’appareil. La clause FROM indique le regroupement de documents sur lequel elle doit être itérée (devices, devices.modules ou devices.jobs).

Ensuite, le filtre dans la clause WHERE est appliqué. Avec des agrégations, les résultats de cette étape sont regroupés tel que spécifié dans la clause GROUP BY. Pour chaque groupe, une ligne est générée tel que spécifié dans la clause SELECT.

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

Clause SELECT

La clause SELECT <select_list> est requise dans chaque requête IoT Hub. Elle spécifie les valeurs qui sont récupérées de la requête. Elle spécifie les valeurs JSON à utiliser pour générer de nouveaux objets JSON. Pour chaque élément du sous-ensemble filtré (et éventuellement groupé) du regroupement FROM, la phase de projection génère un nouvel objet JSON. Cet objet est construit avec les valeurs spécifiées dans la clause SELECT.

Par exemple :

  • Retourner toutes les valeurs

    SELECT *
    
  • Retourner des propriétés spécifiques

    SELECT DeviceID, LastActivityTime
    
  • Agréger les résultats d’une requête pour retourner un nombre

    SELECT COUNT() as TotalNumber
    

Actuellement, les clauses de sélection autres que SELECT sont prises en charge uniquement dans les requêtes d’agrégation sur des jumeaux d’appareil.

La grammaire de la clause SELECT est la suivante :

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 fait référence à n’importe quelle propriété du document JSON dans le regroupement FROM.

Clause FROM

La clause FROM <from_specification> est requise dans chaque requête IoT Hub. Cela peut être l’une des trois valeurs suivantes :

  • devices pour interroger des jumeaux d'appareil
  • devices.modules pour interroger des jumeaux de module
  • devices.jobs pour interroger les détails du travail par appareil

Par exemple :

  • Récupérer tous les jumeaux d’appareil

    SELECT * FROM devices
    

WHERE, clause

La clause WHERE <filter_condition> est facultative. Elle indique une ou plusieurs conditions que les documents JSON du regroupement FROM doivent remplir pour être inclus dans le résultat. Pour être inclus dans le résultat, chaque document JSON doit évaluer les conditions spécifiées comme « true ».

Par exemple :

  • Récupérer tous les travaux qui ciblent un appareil spécifique

    SELECT * FROM devices.jobs
      WHERE devices.jobs.deviceId = 'myDeviceId'
    

Les conditions autorisées sont décrites dans la section Expressions et conditions.

Clause GROUP BY

La clause GROUP BY <group_specification> est facultative. Cette clause s’exécute après le filtre spécifié dans la clause WHERE et avant la projection spécifiée dans la clause SELECT. Elle groupe des documents en fonction de la valeur d’un attribut. Ces groupes sont utilisés pour générer des valeurs agrégées comme spécifié dans la clause SELECT.

Par exemple :

  • Retourner le nombre d’appareils qui signalent chaque état de configuration de télémétrie

    SELECT properties.reported.telemetryConfig.status AS status,
      COUNT() AS numberOfDevices
    FROM devices
    GROUP BY properties.reported.telemetryConfig.status
    

Actuellement, la clause GROUP BY est prise en charge uniquement lors de l’interrogation de jumeaux d’appareil.

Attention

Le terme group est actuellement traité comme un mot clé spécial dans les requêtes. Si vous utilisez group comme nom de propriété, vous pouvez l’encadrer entre doubles crochets pour éviter les erreurs, par exemple, SELECT * FROM devices WHERE tags.[[group]].name = 'some_value'.

La syntaxe formelle de la clause GROUP BY est la suivante :

GROUP BY <group_by_element>
<group_by_element> :==
    attribute_name
    | < group_by_element > '.' attribute_name

Attribute_name fait référence à n’importe quelle propriété du document JSON dans le regroupement FROM.

Pagination des résultats de la requête

Un objet de requête est instancié avec une taille de page maximale inférieure ou égale à 100 enregistrements. Pour obtenir plusieurs pages, appelez plusieurs fois la méthode nextAsTwin sur le kit de développement logiciel (SDK) Node.js ou GetNextAsTwinAsync sur le SDK .Net. L’objet de requête peut exposer plusieurs valeurs Next, en fonction de l’option de désérialisation requise par la requête. Par exemple, un objet de requête peut retourner les objets de travail ou de jumeau d’appareil, ou le code JSON brut lors de l’utilisation de projections.

Expressions et conditions

À un niveau élevé, une expression :

  • prend la valeur d’une instance d’un type JSON (par exemple, Boolean, number, string, array ou object) ;
  • est définie en manipulant des données provenant du document JSON de l’appareil et des constantes à l’aide de fonctions et d’opérateurs intégrés.

Les Conditions sont des expressions qui correspondent à une valeur booléenne. Toute constante autre qu’une valeur booléenne true est considérée comme false. Cette règle inclut null, undefined, toute instance d’objet ou de tableau, toute chaîne et la valeur booléenne false.

La syntaxe des expressions est la suivante :

<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>]+ ']'

Pour comprendre ce que signifie chaque symbole dans la syntaxe des expressions, consultez le tableau suivant :

Symbole Définition
attribute_name Toute propriété du document JSON dans le regroupement FROM.
binary_operator Tout opérateur binaire répertorié dans la section Operators.
function_name Toutes les fonctions répertoriées dans la section Fonctions.
decimal_literal Variable exprimée en notation décimale.
hexadecimal_literal Nombre exprimé par la chaîne « 0x » suivie d’une chaîne de chiffres hexadécimaux.
string_literal Des chaînes Unicode représentées par une séquence de zéro ou plusieurs caractères Unicode ou séquences d’échappement. Les littéraux de chaîne sont placés entre guillemets simples ou guillemets doubles. Échappements autorisés : \', \", \\, \uXXXX pour les caractères Unicode définis par quatre chiffres hexadécimaux.

Opérateurs

Les opérateurs suivants sont pris en charge :

Famille Opérateurs
Arithmétique +, -, *, /, %
Logical AND, OR, NOT
Comparaison =, !=, <, >, <=, >=, <>

Fonctions

Lors des requêtes de jumeaux ou de travaux, la seule fonction prise en charge est :

Fonction Description
IS_DEFINED(property) Retourne une valeur booléenne indiquant si une valeur a été attribuée à la propriété (dont null).

Dans les conditions d’itinéraire, les fonctions mathématiques suivantes sont prises en charge :

Fonction Description
ABS(x) Retourne la valeur (positive) absolue de l'expression numérique spécifiée.
EXP(x) Retourne la valeur exponentielle de l'expression numérique spécifiée (e^x).
POWER(x,y) Retourne la valeur de l’expression spécifiée élevée à la puissance spécifiée (x^y).
SQUARE(x) Retourne le carré de la valeur numérique spécifiée.
CEILING(x) Retourne le plus petit nombre entier qui est supérieur ou égal à l'expression numérique spécifiée.
FLOOR(x) Renvoie le nombre entier le plus grand, inférieur ou égal à l'expression numérique donnée.
SIGN(x) Retourne le signe positif (+1), nul (0) ou négatif (-1) de l'expression numérique spécifiée.
SQRT(x) Retourne la racine carrée de la valeur numérique spécifiée.

Dans les conditions d’itinéraire, les fonctions de vérification et de conversion de type suivantes sont prises en charge :

Fonction Description
AS_NUMBER Convertit la chaîne d’entrée en nombre. noop si l’entrée est un nombre ; Undefined si la chaîne ne représente pas un nombre.
IS_ARRAY Retourne une valeur booléenne indiquant si l’expression spécifiée est du type tableau.
IS_BOOL Retourne une valeur booléenne indiquant si l’expression spécifiée est du type booléen.
IS_DEFINED Retourne une valeur booléenne indiquant si une valeur a été attribuée à la propriété. Cette fonction est uniquement prise en charge lorsque la valeur est de type primitif. Exemples de types primitifs : chaîne, booléen, numérique ou null. DateHeure, les types d'objets et les tableaux ne sont pas pris en charge.
IS_NULL Retourne une valeur booléenne indiquant si l’expression spécifiée est de type null.
IS_NUMBER Retourne une valeur booléenne indiquant si l’expression spécifiée est du type nombre.
IS_OBJECT Retourne une valeur booléenne indiquant si l’expression spécifiée est du type objet JSON.
IS_PRIMITIVE Retourne une valeur booléenne indiquant si l’expression spécifiée est de type primitif (chaîne, booléen, numérique ou null).
IS_STRING Retourne une valeur booléenne indiquant si l’expression spécifiée est du type chaîne.

Dans les conditions d’itinéraire, les fonctions de chaîne suivantes sont prises en charge :

Fonction Description
CONCAT(x, y, …) Retourne une chaîne qui est le résultat de la concaténation d’au moins deux valeurs de chaîne.
LENGTH(x) Retourne le nombre de caractères de l’expression de chaîne spécifiée.
LOWER(x) Retourne une expression de chaîne après la conversion des caractères majuscules en caractères minuscules.
UPPER(x) Retourne une expression de chaîne après la conversion des caractères minuscules en caractères majuscules.
SUBSTRING(string, start [, length]) Renvoie une partie d’une expression de chaîne commençant à la position de caractère spécifiée (avec base zéro) et se poursuit jusqu'à la longueur spécifiée ou à la fin de la chaîne.
INDEX_OF(string, fragment) Retourne la position de départ de la première occurrence de la seconde expression de chaîne dans la première expression de chaîne spécifiée, ou -1 si la chaîne est introuvable.
STARTSWITH(x, y) Retourne une valeur booléenne indiquant si la première expression de chaîne commence par la seconde.
ENDSWITH(x, y) Retourne une valeur booléenne indiquant si la première expression de chaîne se termine par la seconde.
CONTAINS(x,y) Retourne une valeur booléenne indiquant si la première expression de chaîne contient la seconde.

Exemples de requête avec les SDK de service

Exemple en code C#

La fonctionnalité de requête est exposée par Service SDK C# dans la classe RegistryManager.

Voici un exemple de requête simple :

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

L’objet de requête est instancié avec les paramètres mentionnés dans la section pagination des résultats de la requête. Plusieurs pages sont récupérées en appelant plusieurs fois les méthodes GetNextAsTwinAsync.

Exemple de Node.js

La fonctionnalité de requête est exposée par le Kit Azure IoT service SDK pour Node.js dans l’objet Registry.

Voici un exemple de requête simple :

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

L’objet de requête est instancié avec les paramètres mentionnés dans la section pagination des résultats de la requête. Plusieurs pages sont récupérées en appelant plusieurs fois la méthode nextAsTwin.

Étapes suivantes