IoT Hub frågespråk för enhets- och modultvillingar, jobb och meddelanderoutning

IoT Hub tillhandahåller ett kraftfullt SQL-liknande språk för att hämta information om enhetstvillingar, modultvillingar, jobb och meddelanderoutning. I den här artikeln beskrivs:

Specifika exempel finns i Frågor för IoT Hub-enheter och modultvillingar eller Frågor för IoT Hub-jobb.

Note

Vissa av de funktioner som nämns i den här artikeln, till exempel meddelanden från moln till enhet, enhetstvillingar och enhetshantering, är endast tillgängliga på standardnivån för IoT Hub. Mer information om de grundläggande och standard-/kostnadsfria IoT Hub-nivåerna finns i Välj rätt IoT Hub-nivå och storlek för din lösning.

Kör IoT Hub-frågor

Du kan köra frågor mot ditt IoT-nav direkt i Azure-portalen.

  1. Logga in på Azure-portalen och navigera till din IoT-hubb.
  2. Välj Queries från sektionen Enhetshantering i navigationsmenyn.
  3. Ange din fråga i textrutan och välj Run query.

Du kan också köra frågor inom dina applikationer med hjälp av Azure IoT tjänste-SDK:er och tjänste-API:er.

Exempel på kod som implementerar IoT Hub frågor finns i avsnittet Query med tjänst-SDK:er.

Länkar till SDK-referenssidor och exempel finns i Azure IoT Hub SDK:er.

Grunderna för en fråga i IoT Hub

Varje IoT Hub-fråga består av SELECT- och FROM-satser, med valfria WHERE- och GROUP BY-satser.

Frågeställningar körs på en samling JSON-dokument, till exempel enhetstvillingar. FROM-satsen anger den dokumentsamling som ska itereras på (antingen enheter, enheter.moduler eller devices.jobs).

Sedan tillämpas filtret i WHERE-satsen. Med aggregeringar grupperas resultatet av det här steget enligt beskrivningen i GROUP BY-satsen. För varje grupp genereras en rad enligt vad som anges i SELECT-satsen.

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

SELECT-klausul

Satsen SELECT <select_list> krävs i varje IoT Hub-fråga. Den anger vilka värden som hämtas från frågan. Den anger de JSON-värden som ska användas för att generera nya JSON-objekt. För varje element i den filtrerade (och eventuellt grupperade) delmängden av FROM-samlingen, genererar projektionsfasen ett nytt JSON-objekt. Detta objekt är konstruerat med de värden som anges i SELECT-satsen.

Som exempel:

  • Återställ alla värden

    SELECT *
    
  • Returnera specifika egenskaper

    SELECT DeviceID, LastActivityTime
    
  • Sammanställ resultaten av en fråga för att returnera ett antal

    SELECT COUNT() as TotalNumber
    

För närvarande stöds bara urvalssatser som skiljer sig från SELECT i aggregerade frågor på enhetstvillingar.

Den följande syntaxen är grammatiken för SELECT-satsen:

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 refererar till alla egenskaper för JSON-dokumentet i FROM-samlingen.

FROM-sats

FROM <from_specification> Satsen krävs i varje ioT Hub-fråga. Det måste vara ett av tre värden:

  • enheter för att läsa av enhetstvillingar
  • devices.modules för att fråga modultvillingar
  • devices.jobs för att fråga efter jobbinformation per enhet

Som exempel:

  • Hämta alla enhetstvillingar

    SELECT * FROM devices
    

WHERE-klausul

Satsen WHERE <filter_condition> är valfri. Den anger ett eller flera villkor som JSON-dokumenten i FROM-samlingen måste uppfylla för att inkluderas som en del av resultatet. Alla JSON-dokument måste utvärdera de angivna villkoren till true för att inkluderas i resultatet.

Som exempel:

  • Hämta alla jobb som riktar sig mot en specifik enhet

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

De tillåtna villkoren beskrivs i avsnittet Uttryck och villkor .

GROUP BY-uttryck

Satsen GROUP BY <group_specification> är valfri. Den här satsen körs efter filtret som anges i WHERE-satsen och före den projektion som anges i SELECT. Den grupperar dokument baserat på värdet av ett attribut. Dessa grupper används för att generera aggregerade värden enligt vad som anges i SELECT-satsen.

Som exempel:

  • Returnera antalet enheter som rapporterar varje telemetrikonfigurationsstatus

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

För närvarande stöds endast GROUP BY-satsen när man frågar efter enheters tvillingar.

Caution

Termgruppen behandlas för närvarande som ett särskilt nyckelord i frågor. Om du använder group som egenskapsnamn bör du överväga att omge den med dubbla hakparenteser för att undvika fel, som du ser i det här exemplet: SELECT * FROM devices WHERE tags.[[group]].name = 'some_value'.

Den formella syntaxen för GROUP BY är:

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

Attribute_name refererar till alla egenskaper för JSON-dokumentet i FROM-samlingen.

Pagineringsresultat för sökfrågor

Ett frågeobjekt instansieras med en maxsidstorlek på mindre än eller lika med 100 poster. Om du vill hämta flera sidor anropar du nextAsTwin på Node.js SDK eller GetNextAsTwinAsync på .NET SDK-metoden flera gånger. Ett frågeobjekt kan exponera flera Nästa-värden, beroende på vilket deserialiseringsalternativ som krävs av frågan. Till exempel kan ett frågeobjekt returnera enhetsdubblering eller jobbobjekt, eller ren JSON när man använder projektioner.

Uttryck och villkor

På en hög nivå, en expression:

  • Utvärderar till en instans av en JSON-typ (till exempel boolesk, tal, sträng, matris eller objekt).
  • Definieras genom att manipulera data som kommer från enhetens JSON-dokument och konstanter med hjälp av inbyggda operatorer och funktioner.

Villkor är uttryck som utvärderas till ett booleskt värde. Varje konstant som skiljer sig från Boolesk true betraktas som false. Den här regeln inkluderar null, undefined, vilken som helst av objekt eller arrayinstans, vilken som helst sträng, och Booleanskt false.

Syntaxen för uttryck är:

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

Information om vad varje symbol i uttryckssyntaxen står för finns i följande tabell:

Symbol Definition
attribut_namn Vilken egenskap som helst av JSON-dokumentet i FROM-samlingen.
binary_operator Alla binära operatorer som anges i avsnittet Operatorer .
function_name Vilken funktion som helst som listas i avsnittet Functions.
decimal_literal Ett flyttal uttryckt i decimal notation.
hexadecimal_literal Ett tal uttryckt av strängen '0x' följt av en sträng av hexadecimala siffror.
string_literal Unicode-strängar som representeras av en sekvens med noll eller fler Unicode-tecken eller escape-sekvenser. Strängliteraler omsluts av enkla citattecken eller dubbla citattecken. Tillåtna escape-sekvenser: \', \", \\, \uXXXX för Unicode-tecken definierade av fyra hexadecimal siffror.

Operators

Följande operatorer stöds:

Family Operators
Aritmetik +, -, *, /, %
Logical OCH, ELLER, INTE
Jämförelse =, !=, <, >, <=, >=, <>

Functions

När man frågar efter tvillingar och jobb är den enda stödda funktionen:

Funktion Beskrivning
IS_DEFINED(property) Returnerar ett booleskt värde som anger om egenskapen har tilldelats ett värde (inklusive null).

I villkor för rutter stöds följande matematikfunktioner:

Funktion Beskrivning
ABS(x) Returnerar det absoluta värdet (positivt) för det angivna numeriska uttrycket.
EXP(x) Returnerar exponentiellt värde för det angivna numeriska uttrycket (e^x).
POTENS(x,y) Returnerar värdet för det angivna uttrycket till den angivna kraften (x^y).
SQUARE(x) Returnerar kvadraten av det angivna numeriska värdet.
CEILING(x) Returnerar det minsta heltalsvärdet som är större än eller lika med det angivna numeriska uttrycket.
FLOOR(x) Returnerar det största heltalet som är mindre än eller lika med det angivna numeriska uttrycket.
SIGN(x) Returnerar tecknet positiv (+1), noll (0) eller negativ (-1) för det angivna numeriska uttrycket.
SQRT(x) Returnerar kvadratroten av det angivna numeriska värdet.

I vägförhållanden stöds följande typkontroll- och gjutningsfunktioner:

Funktion Beskrivning
AS_NUMBER Konverterar indatasträngen till ett tal. noop om inmatningen är ett tal; Undefined om strängen inte representerar ett tal.
IS_ARRAY Återlämnar ett Boolean-värde som indikerar om typen av det angivna uttrycket är en array.
IS_BOOL Returnerar ett Booleskt värde som indikerar om typen av det angivna uttrycket är ett Booleskt.
IS_DEFINED Returnerar ett booleskt värde som anger om egenskapen är ett värde. Den här funktionen stöds endast när värdet är av en primitiv typ. Primitiva typer är sträng, boolesk, numerisk eller null. DateTime, objekttyper och matriser stöds inte.
IS_NULL Returnerar ett booleskt värde som anger om typen på det angivna uttrycket är null.
IS_NUMBER Returnerar ett Boolean-värde som anger om typen av det angivna uttrycket är ett tal.
IS_OBJECT Returnerar ett booleskt värde som indikerar om typen för det angivna uttrycket är ett JSON-objekt.
IS_PRIMITIVE Returnerar ett Booleskt värde som anger om typen av det angivna uttrycket är en primitiv (sträng, Boolean, numerisk eller null).
ÄR_STRÄNG Returnerar ett Boolean-värde som anger om typen av det angivna uttrycket är en sträng.

I villkoren för rutterna stöds följande strängfunktioner:

Funktion Beskrivning
CONCAT(x, y, ...) Returnerar en sträng som är resultatet av att sammanfoga två eller fler strängvärden.
LENGTH(x) Returnerar antalet tecken i det angivna stränguttrycket.
LOWER(x) Returnerar ett stränguttryck efter att ha konverterat data med versaler till gemener.
UPPER(x) Returnerar ett strenguttryck efter att ha konverterat gemen teckendata till versaler.
SUBSTRING(string, start [, length]) Returnerar en del av en stränguttryck som börjar vid den angivna positionen, baserat på nollindex, och fortsätter till den angivna längden, eller till slutet av strängen.
INDEX_OF(sträng, fragment) Returnerar startpositionen för första förekomsten av det andra stränguttrycket inom det första angivna stränguttrycket, eller -1 om strängen inte hittas.
BÖRJAR_MED(x, y) Returnerar ett booleskt värde som indikerar om det första stränguttrycket börjar med det andra.
SLUTAR_MED(x, y) Returnerar ett Boolean-värde som anger om det första stränguttrycket slutar med det andra.
CONTAINS(x,y) Returnerar ett booleskt värde som anger om det första stränguttrycket innehåller det andra.

Frågeexempel med tjänstens SDK:er

C#-exempel

Frågefunktionen exponeras av Azure IoT Hub service SDK för .NET i klassen RegistryManager.

Här är ett exempel på en enkel fråga:

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

Frågeobjektet instansieras med parametrarna som nämns i sidnumreringsavsnittet Frågeresultat . Flera sidor hämtas genom att anropa GetNextAsTwinAsync metoderna flera gånger.

Node.js exempel

Frågefunktionen exponeras av Azure IoT Hub service SDK för Node.js i objektet Registry.

Här är ett exempel på en enkel fråga:

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

Frågeobjektet instansieras med parametrarna som nämns i sidnumreringsavsnittet Frågeresultat . Flera sidor hämtas genom att metoden anropas nextAsTwin flera gånger.

Frågor om IoT Hub enhets- och modultvillingar

Enhetstvillingar och modultvillingar kan innehålla godtyckliga JSON-objekt som både taggar och egenskaper. IoT Hub gör att du kan fråga enhetstvillingar och modultvillingar som ett enda JSON-dokument som innehåller all tvillinginformation.

Här är ett exempel på en IoT Hub-enhetstvilling (modultvillingen skulle vara liknande bara med en parameter för moduleId):

{
    "deviceId": "myDeviceId",
    "etag": "AAAAAAAAAAc=",
    "status": "enabled",
    "statusUpdateTime": "0001-01-01T00:00:00",
    "connectionState": "Disconnected",
    "lastActivityTime": "0001-01-01T00:00:00",
    "cloudToDeviceMessageCount": 0,
    "authenticationType": "sas",
    "x509Thumbprint": {
        "primaryThumbprint": null,
        "secondaryThumbprint": null
    },
    "version": 2,
    "tags": {
        "location": {
            "region": "US",
            "plant": "Redmond43"
        }
    },
    "properties": {
        "desired": {
            "telemetryConfig": {
                "configId": "db00ebf5-eeeb-42be-86a1-458cccb69e57",
                "sendFrequencyInSecs": 300
            },
            "$metadata": {
            ...
            },
            "$version": 4
        },
        "reported": {
            "connectivity": {
                "type": "cellular"
            },
            "telemetryConfig": {
                "configId": "db00ebf5-eeeb-42be-86a1-458cccb69e57",
                "sendFrequencyInSecs": 300,
                "status": "Success"
            },
            "$metadata": {
            ...
            },
            "$version": 7
        }
    }
}

Sökfrågor om enhetstvillingar

IoT Hub exponerar enhetstvillingarna som en dokumentsamling med namnet enheter. Den mest grundläggande frågan hämtar till exempel hela uppsättningen enhetstvillingar:

SELECT * FROM devices

Note

Azure IoT SDK:ar stöder paginering av stora resultat.

Du kan aggregera resultatet av en fråga med hjälp av SELECT-satsen. Till exempel kan följande fråga räkna det totala antalet enheter i en IoT-hubb:

SELECT COUNT() as totalNumberOfDevices FROM devices

Filtrera frågeresultat med hjälp av WHERE-satsen. Om du till exempel vill ta emot enhetstvillingar där taggen location.region är inställd på USA använder du följande fråga:

SELECT * FROM devices
WHERE tags.location.region = 'US'

Skapa komplexa WHERE-satser med hjälp av booleska operatorer och aritmetiska jämförelser. Exempelvis hämtar följande fråga enhetstvillingar som finns i USA och är konfigurerade för att skicka telemetri mindre ofta än en gång per minut.

SELECT * FROM devices
  WHERE tags.location.region = 'US'
    AND properties.reported.telemetryConfig.sendFrequencyInSecs >= 60

Du kan också använda matriskonstanter med operatorerna IN och NIN (inte i). Följande fråga hämtar till exempel enhetstvillingar som rapporterar wi-fi eller kabelansluten anslutning:

SELECT * FROM devices
  WHERE properties.reported.connectivity IN ['wired', 'wifi']

Det är ofta nödvändigt att identifiera alla enhetstvillingar som innehåller en specifik egenskap. IoT Hub stöder funktionen is_defined() för detta ändamål. Följande fråga hämtar till exempel enhetstvillingar som definierar connectivity egenskapen:

SELECT * FROM devices
  WHERE is_defined(properties.reported.connectivity)

Se avsnittet WHERE-sats för att se den fullständiga referensen för filtreringsfunktionerna.

Gruppering stöds också. Följande fråga returnerar till exempel antalet enheter i varje telemetrikonfigurationsstatus:

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

Den här grupperingsfrågan returnerar ett resultat som liknar följande exempel:

[
    {
        "numberOfDevices": 3,
        "status": "Success"
    },
    {
        "numberOfDevices": 2,
        "status": "Pending"
    },
    {
        "numberOfDevices": 1,
        "status": "Error"
    }
]

I det här exemplet rapporterade tre enheter att konfigurationen lyckades, två tillämpar fortfarande konfigurationen och en rapporterade ett fel.

Projektionsfrågor gör det möjligt för utvecklare att endast returnera de egenskaper de bryr sig om. Om du till exempel vill hämta den senaste aktivitetstiden tillsammans med enhets-ID:t för alla aktiverade enheter som är frånkopplade använder du följande fråga:

SELECT DeviceId, LastActivityTime FROM devices WHERE status = 'enabled' AND connectionState = 'Disconnected'

Resultatet av frågan skulle se ut som i följande exempel:

[
  {
    "deviceId": "AZ3166Device",
    "lastActivityTime": "2021-05-07T00:50:38.0543092Z"
  }
]

Frågor om modultvillingar

Att fråga efter modultvillingar liknar att fråga efter enhetstvillingar, men att använda en annan samling/namnrymd. i stället för från devicesfrågar du från devices.modules:

SELECT * FROM devices.modules

Vi tillåter inte en sammanfogning mellan kollektionerna enheter och enheter.modules. Om du vill göra förfrågningar om modultvillingar på olika enheter, gör du det baserat på taggar. Följande fråga returnerar alla modultvillingar på alla enheter med skanningsstatus:

SELECT * FROM devices.modules WHERE properties.reported.status = 'scanning'

Följande fråga returnerar alla modultvillingar med genomsökningsstatus, men endast på den angivna delmängden av enheter:

SELECT * FROM devices.modules
  WHERE properties.reported.status = 'scanning'
  AND deviceId IN ['device1', 'device2']

Begränsningar för tvillingfrågor

Important

Frågeresultat är slutligen konsekventa operationer och fördröjningar på upp till 30 minuter bör tolereras. I de flesta fall returnerar samma förfrågan resultat inom några sekunder. IoT Hub strävar efter att ge låg svarstid för alla åtgärder. Men på grund av nätverksförhållanden och andra oförutsägbara faktorer kan det inte garantera en viss svarstid.

Ett alternativ till tvillingfrågor är att fråga enskilda enhetstvillingar efter ID med hjälp av REST-API:et för att hämta tvilling. Det här API:et returnerar alltid de senaste värdena och har högre begränsningsgränser. Du kan utfärda REST-API:et direkt eller använda motsvarande funktioner i någon av Azure IoT Hub Service SDK:erna.

Frågeuttryck kan ha en maximal längd på 8 192 tecken.

För närvarande stöds jämförelser endast mellan primitiva typer (inga objekt), till exempel ... WHERE properties.desired.config = properties.reported.config stöds endast om dessa egenskaper har primitiva värden.

Vi rekommenderar att du inte förlitar dig på lastActivityTime som finns i enhetsidentitetsegenskaper för tvillingfrågor för något scenario. Det här fältet garanterar inte en korrekt indikator för enhetens status. Använd i stället IoT-enhetslivscykelhändelser för att hantera enhetstillstånd och aktiviteter. Information om hur du använder IoT Hub livscykelhändelser i din lösning finns i Reagera på IoT Hub-händelser genom att använda Event Grid för att utlösa åtgärder.

Note

Undvik att göra några antaganden om den maximala svarstiden för den här åtgärden. Mer information om hur du skapar din lösning med hänsyn till svarstid finns i Svarstidslösningar .

Frågor för IoT Hub jobb

Jobb är ett sätt att köra åtgärder på uppsättningar med enheter. Varje enhetstvilling innehåller information om de jobb som riktar sig mot den i en samling som kallas jobb. IoT Hub gör att du kan göra förfrågningar om jobb som ett enda JSON-dokument som innehåller all tvillinginformation.

Här är ett exempel på en IoT Hub-enhetstvilling som ingår i ett jobb som heter myJobId:

{
    "deviceId": "myDeviceId",
    "etag": "AAAAAAAAAAc=",
    "tags": {
        ...
    },
    "properties": {
        ...
    },
    "jobs": [
        {
            "deviceId": "myDeviceId",
            "jobId": "myJobId",
            "jobType": "scheduleUpdateTwin",
            "status": "completed",
            "startTimeUtc": "2016-09-29T18:18:52.7418462",
            "endTimeUtc": "2016-09-29T18:20:52.7418462",
            "createdDateTimeUtc": "2016-09-29T18:18:56.7787107Z",
            "lastUpdatedDateTimeUtc": "2016-09-29T18:18:56.8894408Z",
            "outcome": {
                "deviceMethodResponse": null
            }
        },
        ...
    ]
}

För närvarande kan denna samling frågas som devices.jobs i IoT Hub-förfrågningsspråket.

Important

För närvarande returneras inte jobbegenskapen när man frågar mot enhetstvillingar. Det vill: frågor som innehåller FROM devices. Egenskapen 'jobb' kan endast nås direkt genom att använda frågor med FROM devices.jobs.

Följande fråga returnerar till exempel alla jobb (tidigare och schemalagda) som påverkar en enskild enhet:

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

Observera hur den här frågan ger enhetsspecifik status (och eventuellt direktmetodsvaret) för varje jobb som returneras.

Det går också att filtrera med godtyckliga booleska villkor för alla objektegenskaper i devices.jobs samlingen.

Följande fråga hämtar till exempel alla slutförda uppdateringsjobb för enhetstvillingar som skapades efter september 2016 för en specifik enhet:

SELECT * FROM devices.jobs
  WHERE devices.jobs.deviceId = 'myDeviceId'
    AND devices.jobs.jobType = 'scheduleUpdateTwin'
    AND devices.jobs.status = 'completed'
    AND devices.jobs.createdTimeUtc > '2016-09-01'

Du kan också hämta resultatet per enhet för ett enda jobb.

SELECT * FROM devices.jobs
  WHERE devices.jobs.jobId = 'myJobId'

Begränsningar för arbetsfrågor

Frågeuttryck kan ha en maximal längd på 8 192 tecken.

För närvarande stöder inte frågor på devices.jobs :

  • Projektioner är därför bara SELECT * möjliga.
  • Villkor som refererar till enhetstvillingen utöver jobbegenskaper (se föregående avsnitt).
  • Sammansättningar, till exempel antal, medelvärde och group by.
  • Lär dig mer om routning av meddelanden baserat på meddelandeegenskaper eller meddelandetext med frågesyntaxen IoT Hub meddelanderoutning.