IoT Hub-Abfragesprache für Geräte- und Modulzwillinge, Aufträge und Nachrichtenrouting

IoT Hub verfügt über eine leistungsstarke SQL-ähnliche Sprache zum Abrufen von Informationen zu Gerätezwillingen, Modulzwillingen, Aufträgen und zum Nachrichtenrouting. Dieser Artikel enthält Folgendes:

  • Eine Einführung in die wichtigsten Features der IoT Hub-Abfragesprache
  • Eine ausführliche Beschreibung der Sprache Weitere Informationen zur Abfragesprache für das Nachrichtenrouting finden Sie unter Abfragen im Nachrichtenrouting.

Konkrete Beispiele finden Sie unter Abfragen für Geräte- und Modulzwillinge oder Abfragen für Aufträge.

Hinweis

Einige der in diesem Artikel erwähnten Features (wie Cloud-zu-Gerät-Messaging, Gerätezwillinge und Geräteverwaltung) stehen nur im Standard-Tarif von IoT Hub zur Verfügung. Weitere Informationen zu den IoT Hub-Tarifen „Basic“ und „Standard/Free“ finden Sie unter Wählen des richtigen IoT Hub-Tarifs für Ihre Lösung.

Ausführen IoT Hub-Abfragen

Sie können Abfragen für Ihren IoT-Hub direkt im Azure-Portal ausführen.

  1. Melden Sie sich beim Azure-Portal an, und navigieren Sie zu Ihrem IoT Hub.
  2. Wählen Sie Abfragen im Abschnitt Geräteverwaltung des Navigationsmenüs aus.
  3. Geben Sie eine Abfrage in das Textfeld ein und wählen Sie Abfrage ausführen aus.

Sie können auch Abfragen in Ihren Anwendungen mit den Azure IoT-Dienst-SDKs und Dienst-APIs ausführen.

Beispielcode zur Implementierung von IoT Hub-Abfragen finden Sie im Abschnitt Abfragebeispiele mit den Dienst-SDKs.

Links zu SDK-Referenzseiten und Beispielen finden Sie unter Azure IoT SDKs.

Grundlagen von IoT Hub-Abfragen

Jede IoT Hub-Abfrage besteht aus einer SELECT- und einer FROM-Klausel mit optionalen WHERE- und GROUP BY-Klauseln.

Abfragen werden für eine Sammlung von JSON-Dokumenten ausgeführt, z. B. Gerätezwillinge. Die FROM-Klausel zeigt die Dokumentsammlung an, die durchlaufen werden soll (entweder devices, devices.modules oder devices.jobs).

Anschließend wird der Filter in der WHERE-Klausel angewendet. Mit Aggregationen werden die Ergebnisse dieses Schritts gruppiert, wie in der GROUP BY-Klausel angegeben. Für jede Gruppe wird eine Zeile generiert, wie in der SELECT-Klausel angegeben.

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

SELECT-Klausel

Die Klausel SELECT <select_list> ist in jeder IoT Hub-Abfrage erforderlich. Sie gibt an, welche Werte von der Abfrage abgerufen werden. Sie gibt die JSON-Werte an, mit denen die neuen JSON-Objekte erstellt werden sollen. Für jedes Element der gefilterten (und optional gruppierten) Teilmenge der FROM-Sammlung wird in der Projektionsphase ein neues JSON-Objekt generiert. Dieses Objekt wird mit den in der SELECT-Klausel angegebenen Werten erstellt.

Beispiel:

  • Rückgabe aller Werte

    SELECT *
    
  • Rückgabe spezifischer Eigenschaften

    SELECT DeviceID, LastActivityTime
    
  • Aggregieren der Ergebnisse einer Abfrage, um eine Anzahl zurückzugeben

    SELECT COUNT() as TotalNumber
    

Derzeit werden andere Auswahlklauseln als SELECT nur in Aggregatabfragen für Gerätezwillinge unterstützt.

Die folgende Syntax ist die Grammatik der SELECT-Klausel:

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 bezieht sich auf jede Eigenschaft des JSON-Dokuments in der FROM-Sammlung.

FROM-Klausel

Die Klausel FROM <from_specification> in jeder IoT Hub-Abfrage erforderlich. Dies muss einer von drei Werten sein:

  • devices zum Abfragen von Gerätezwillingen
  • devices.modules zum Abfragen von Modulzwillingen
  • devices.jobs zum Abfragen von Auftragsdetails pro Gerät

Beispiel:

  • Abrufen aller Gerätezwillinge

    SELECT * FROM devices
    

WHERE-Klausel

Die Klausel WHERE <filter_condition> ist optional. Sie gibt eine oder mehrere Bedingungen an, die von den in der FROM-Sammlung enthaltenen JSON-Dokumenten erfüllt werden müssen, um als Teil des Ergebnisses zurückgegeben zu werden. Jedes JSON-Dokument muss die angegebenen Bedingungen erfüllen, um in das Ergebnis einbezogen zu werden.

Beispiel:

  • Abrufen aller Aufträge, die auf ein bestimmtes Gerät abzielen

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

Die zulässigen Bedingungen sind im Abschnitt Ausdrücke und Bedingungen beschrieben.

GROUP BY-Klausel

Die Klausel GROUP BY <group_specification> ist optional. Diese Klausel wird nach dem in der WHERE-Klausel angegebenen Filter und vor der in SELECT angegebenen Projektion ausgeführt. Sie gruppiert Dokumente anhand des Werts eines Attributs. Diese Gruppen werden verwendet, um aggregierte Werte gemäß der SELECT-Klausel zu generieren.

Beispiel:

  • Zurückgeben der Anzahl der Geräte, die jeden Status für die Telemetriekonfiguration melden

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

Die GROUP BY-Klausel wird derzeit nur für Abfragen von Gerätezwillingen unterstützt.

Achtung

Der Begriff group wird derzeit in Abfragen als spezielles Schlüsselwort behandelt. Wenn Sie group als Eigenschaftenname verwenden, sollten Sie ihn zur Vermeidung von Fehlern in doppelte Klammern einschließen, z.B. SELECT * FROM devices WHERE tags.[[group]].name = 'some_value'.

Die formale Syntax für GROUP BY lautet:

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

Attribute_name bezieht sich auf jede Eigenschaft des JSON-Dokuments in der FROM-Sammlung.

Paginierung von Abfrageergebnissen

Ein Abfrageobjekt wird mit einer maximalen Seitengröße von kleiner als oder gleich 100 Datensätzen instanziiert. Um mehrere Seiten abzurufen, rufen Sie mehrmals die Methode nextAsTwin für das Node.js SDK oder GetNextAsTwinAsync für das .NET SDK auf. Ein Abfrageobjekt kann mehrere Next-Werte verfügbar machen, abhängig von der Deserialisierungsoption, die von der Abfrage benötigt wird. Ein Abfrageobjekt kann beispielsweise Gerätezwillings- bzw. Auftragsobjekte oder einfachen JSON-Text bei der Verwendung von Projektionen zurückgeben.

Ausdrücke und Bedingungen

Auf hoher Ebene wird ein Ausdruck:

  • in eine Instanz eines JSON-Typs (z. B. boolescher Wert, Zahl, Zeichenfolge, Array oder Objekt) ausgewertet.
  • durch das Ändern von Daten aus dem JSON-Dokument des Geräts und Konstanten mit integrierten Operatoren und Funktionen definiert.

Bedingungen sind Ausdrücke, die als boolescher Wert ausgewertet werden. Jede Konstante, die sich vom booleschen Ausdruck true unterscheidet, wird als false betrachtet. Diese Regel umfasst null, undefined, jede Objekt- oder Arrayinstanz, jede Zeichenfolge und den booleschen Ausdruck false.

Die Syntax für Ausdrücke lautet:

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

Informationen dazu, wofür die einzelnen Symbole in der Ausdruckssyntax stehen, finden Sie in der folgenden Tabelle:

Symbol Definition
attribute_name Eine beliebige Eigenschaft des JSON-Dokuments in der FROM-Sammlung.
binary_operator Ein beliebiger binärer, im Abschnitt Operatoren aufgelisteter Operator.
function_name Eine beliebige im Abschnitt Funktionen aufgelistete Funktion.
decimal_literal Ein Gleitkommawert, ausgedrückt in Dezimalschreibweise.
hexadecimal_literal Eine Zahl, ausgedrückt durch die Zeichenfolge „0x“ gefolgt von einer Zeichenfolge von Hexadezimalzahlen.
string_literal Unicode-Zeichenfolgen, die durch eine Sequenz aus null oder mehr Unicode-Zeichen oder Escapesequenzen dargestellt werden. Zeichenfolgenliterale werden in einfache Anführungszeichen oder doppelte Anführungszeichen eingeschlossen. Zulässige Escapezeichen: \', \", \\, \uXXXX für Unicode-Zeichen, die durch vier Hexadezimalstellen definiert werden.

Operatoren

Die folgenden Operatoren werden unterstützt:

Familie Operatoren
Arithmetik +, -, *, /, %
Logisch AND, OR, NOT
Vergleich =, !=, <, >, <=, >=, <>

Functions

Bei Abfragen von Zwillingen und Aufträgen wird nur folgende Funktion unterstützt:

Funktion BESCHREIBUNG
IS_DEFINED(Eigenschaft) Gibt einen booleschen Wert zurück, um anzugeben, ob der Eigenschaft ein Wert zugewiesen wurde (inklusive null).

In Routenbedingungen werden die folgenden mathematischen Funktionen unterstützt:

Funktion BESCHREIBUNG
ABS(x) Gibt den absoluten (positiven) Wert des angegebenen numerischen Ausdrucks zurück.
EXP(x) Gibt den Exponentialwert des angegebenen numerischen Ausdrucks (e^x) zurück.
POWER(x,y) Gibt den Wert des angegebenen Ausdrucks gemäß der angegebenen Potenz (x^y) zurück.
SQUARE(x) Gibt die Quadratwurzel des angegebenen numerischen Werts zurück.
CEILING(x) Gibt den kleinsten ganzzahligen Wert zurück, der größer oder gleich dem angegebenen numerischen Ausdruck ist.
FLOOR(x) Gibt die größte ganze Zahl zurück, die kleiner oder gleich dem angegebenen numerischen Ausdruck ist.
SIGN(x) Gibt das positive Vorzeichen (+1), null (0) oder das negative Vorzeichen (-1) des angegebenen numerischen Ausdrucks zurück.
SQRT(x) Gibt die Quadratwurzel des angegebenen numerischen Werts zurück.

In Routenbedingungen werden die folgenden Typüberprüfungs- und Umwandlungsfunktionen unterstützt:

Funktion BESCHREIBUNG
AS_NUMBER Konvertiert die Eingabezeichenfolge in eine Zahl. noop, wenn die Eingabe eine Zahl ist; Undefined, wenn die Zeichenfolge keine Zahl darstellt.
IS_ARRAY Gibt einen booleschen Wert zurück, der angibt, ob der angegebene Ausdruck vom Typ „Array“ ist.
IS_BOOL Gibt einen booleschen Wert zurück, der angibt, ob der angegebene Ausdruck vom Typ „boolesch“ ist.
IS_DEFINED Gibt einen booleschen Wert zurück, um anzugeben, ob der Eigenschaft ein Wert zugewiesen wurde. Diese Funktion wird nur unterstützt, wenn es sich bei dem Wert um einen primitiven Typ handelt. Primitive Typen umfassen Zeichenfolgen, boolesche Werte, numerische Werte und null. DateTime, Objekttypen und Arrays werden nicht unterstützt.
IS_NULL Gibt einen booleschen Wert zurück, der angibt, ob der angegebene Ausdruck vom Typ „NULL“ ist.
IS_NUMBER Gibt einen booleschen Wert zurück, der angibt, ob der angegebene Ausdruck vom Typ „Zahl“ ist.
IS_OBJECT Gibt einen booleschen Wert zurück, der angibt, ob der angegebene Ausdruck vom Typ „JSON-Objekt“ ist.
IS_PRIMITIVE Gibt einen booleschen Wert zurück, der angibt, ob der angegebene Ausdruck ein Grundtyp ist (Zeichenfolge, boolesch, numerisch oder null).
IS_STRING Gibt einen booleschen Wert zurück, der angibt, ob der angegebene Ausdruck vom Typ „Zeichenfolge“ ist.

In Routenbedingungen werden die folgenden Zeichenfolgenfunktionen unterstützt:

Funktion BESCHREIBUNG
CONCAT(x, y, …) Gibt eine Zeichenfolge zurück, die das Ergebnis der Verkettung von zwei oder mehr Zeichenfolgenwerten darstellt.
LENGTH(x) Gibt die Anzahl der Zeichen im angegebenen Zeichenfolgenausdruck zurück.
LOWER(x) Gibt eine Zeichenfolge zurück, nachdem Großbuchstaben in Kleinbuchstaben konvertiert wurden.
UPPER(x) Gibt eine Zeichenfolge zurück, nachdem Kleinbuchstaben in Großbuchstaben konvertiert wurden.
SUBSTRING(Zeichenfolge, Start [, Länge]) Gibt einen Teil eines Zeichenfolgenausdrucks zurück. Das angegebene Zeichen ist der Nullpunkt, von dem ab die Teilzeichenfolge in angegebener Länge bzw. bis zum Ende der Zeichenfolge zurückgegeben wird.
INDEX_OF(Zeichenfolge, Fragment) Gibt die Anfangsposition des ersten Vorkommens des zweiten Zeichenfolgenausdrucks innerhalb des ersten angegebenen Zeichenfolgenausdrucks zurück, oder -1, wenn die Zeichenfolge nicht gefunden wird.
STARTSWITH(x, y) Gibt einen booleschen Wert zurück, um anzugeben, ob der erste Zeichenfolgenausdruck mit dem zweiten beginnt.
ENDSWITH(x, y) Gibt einen booleschen Wert zurück, um anzugeben, ob der erste Zeichenfolgenausdruck mit dem zweiten endet.
CONTAINS(x,y) Gibt einen booleschen Wert zurück, um anzugeben, ob der erste Zeichenfolgenausdruck den zweiten enthält.

Abfragebeispiele mit den Dienst-SDKs

C#-Beispiel

Die Abfragefunktion wird durch das C#-Dienst-SDK in der RegistryManager-Klasse verfügbar gemacht.

Hier ein Beispiel einer einfachen Abfrage:

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

Das Abfrageobjekt wird mit den Parametern instanziiert, die im Abschnitt Paginierung von Abfrageergebnissen erwähnt werden. Mehrere Seiten werden durch mehrmaliges Aufrufen der GetNextAsTwinAsync-Methoden aufgerufen.

Node.js-Beispiel

Die Abfragefunktion wird durch das Azure IoT-Dienst-SDK für Node.js im Registry-Objekt verfügbar gemacht.

Hier ein Beispiel einer einfachen Abfrage:

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

Das Abfrageobjekt wird mit den Parametern instanziiert, die im Abschnitt Paginierung von Abfrageergebnissen erwähnt werden. Mehrere Seiten werden durch mehrmaliges Aufrufen der nextAsTwin-Methode aufgerufen.

Nächste Schritte