Linguagem de consulta do Hub IoT para dispositivos e módulos gêmeos, trabalhos e roteamento de mensagens

O Hub IoT oferece uma linguagem avançada semelhante à SQL para recuperação de informações relacionadas a dispositivos gêmeos, módulos gêmeos, trabalhos e roteamento de mensagens. Este artigo apresenta:

  • Uma introdução aos principais recursos da linguagem de consulta do Hub IoT e
  • Uma descrição mais detalhada da linguagem. Para obter detalhes sobre a linguagem de consulta do roteamento de mensagens, confira consultas no roteamento de mensagens.

Para obter exemplos específicos, consulte Consultas para dispositivos e módulos gêmeos ou Consultas para trabalhos.

Observação

Alguns dos recursos mencionados neste artigo, como mensagens de nuvem para dispositivo, dispositivos gêmeos e gerenciamento de dispositivo estão disponíveis somente na camada Standard do Hub IoT. Para obter mais informações sobre as camadas básica e padrão/gratuita do Hub IoT, confira Escolher a camada certa do Hub IoT para a sua solução.

Executar consultas Hub IoT

Você pode executar consultas no Hub IoT diretamente no portal do Azure.

  1. Entre no Portal do Azure e navegue até o Hub IoT.
  2. Selecione Consultas na seção Gerenciamento de dispositivos do menu de navegação.
  3. Insira sua consulta na caixa de texto e selecione Executar consulta.

Você também pode executar consultas em seus aplicativos usando os SDKs do serviço IoT do Azure e as APIs de serviço.

Por exemplo, para ver código implementando consultas Hub IoT, consulte a seção Exemplos de consulta com os SDKs de serviço.

Para obter links para páginas e exemplos de referência do SDK, consulte SDKs do Azure IoT.

Noções básicas de uma consulta de Hub IoT

Todas as consultas de Hub IoT são compostas por cláusulas SELECT e FROM, com cláusulas WHERE e GROUP BY opcionais.

As consultas são executadas em uma coleção de documentos JSON, por exemplo, dispositivos gêmeos. A cláusula FROM indica a coleção de documentos a ser iterada em (devices, devices.modules ou devices.jobs).

Em seguida, o filtro na cláusula WHERE é aplicado. Com agregações, os resultados dessa etapa são agrupados conforme especificado na cláusula GROUP BY. Para cada grupo, uma linha é gerada conforme especificado na cláusula SELECT.

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

Cláusula SELECT

A cláusula SELECT <select_list> é necessária em cada consulta Hub IoT. Ela especifica quais valores são recuperados da consulta. Ela especifica os valores JSON a serem usado para gerar novos objetos JSON. Para cada elemento do subconjunto filtrado (e opcionalmente agrupado) da coleção FROM, a fase de projeção gera um novo objeto JSON. Esse objeto é construído com os valores especificados na cláusula SELECT.

Por exemplo:

  • Retornar todos os valores

    SELECT *
    
  • Retornar propriedades específicas

    SELECT DeviceID, LastActivityTime
    
  • Agregar os resultados de uma consulta para retornar uma contagem

    SELECT COUNT() as TotalNumber
    

No momento, as cláusulas de seleção diferentes de SELECT* têm suporte apenas em consultas de agregação em dispositivos gêmeos.

A sintaxe a seguir é a gramática da cláusula SELECT:

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 refere-se a qualquer propriedade do documento JSON na coleção FROM.

Cláusula FROM

A cláusula FROM <from_specification> é necessária em todas as consultas do Hub IoT. Deve ser um dos três valores:

  • dispositivos para consultar dispositivos gêmeos
  • devices.modules para consultar módulos gêmeos
  • devices.jobs para consultar detalhes do trabalho por dispositivo

Por exemplo:

  • Recuperar todos os dispositivos gêmeos

    SELECT * FROM devices
    

cláusula WHERE

A cláusula WHERE <filter_condition> é opcional. Ela especifica uma ou mais condições que os documentos JSON na coleção FROM devem satisfazer para serem incluídos como parte dos resultados. Todos os documentos JSON devem avaliar as condições especificadas como “true” para ser incluídos no resultado.

Por exemplo:

  • Recuperar todos os trabalhos direcionados a um dispositivo específico

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

As condições permitidas são descritas na seção Expressões e condições.

Cláusula GROUP BY

A cláusula GROUP BY <group_specification> é opcional. Essa cláusula é executada após o filtro especificado na cláusula WHERE e antes da projeção especificada no SELECT. Ela agrupa documentos com base no valor de um atributo. Esses grupos são usados para gerar valores agregados conforme especificado na cláusula SELECT.

Por exemplo:

  • Retornar a contagem de dispositivos que estão relatando cada status de configuração de telemetria

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

No momento, a cláusula GROUP BY tem suporte apenas ao consultar dispositivos gêmeos.

Cuidado

O termo group atualmente é tratado como uma palavra-chave especial em consultas. No caso, você usa group como seu nome de propriedade, considere colocá-lo entre colchetes duplos para evitar erros, por exemplo, SELECT * FROM devices WHERE tags.[[group]].name = 'some_value'.

A sintaxe formal para GROUP BY é:

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

Attribute_name refere-se a qualquer propriedade do documento JSON na coleção FROM.

Paginação de resultados da consulta

Um objeto de consulta é instanciado com um tamanho máximo de página menor ou igual a 100 registros. Para obter várias páginas, chame o método nextAsTwin em Node.js SDK ou GetNextAsTwinAsync no SDK do .Net várias vezes. Um objeto de consulta pode expor vários valores Next, dependendo da opção de desserialização exigida pela consulta. Por exemplo, um objeto de consulta pode retornar dispositivos gêmeos ou objetos de trabalho ou JSON simples ao usar projeções.

Expressões e condições

Em um alto nível, uma expressão:

  • Avalia para uma instância de um tipo JSON (por exemplo, booliano, número, cadeia de caracteres, matriz ou objeto).
  • É definida pela manipulação de dados provenientes do documento JSON de dispositivo e constantes usando as funções e operadores internos.

Condições são expressões que retornam um valor booliano. Qualquer constante diferente do Booliano verdadeiro é considerada como falso. Essa regra inclui nulo, indefinido, qualquer instância de matriz ou objeto, qualquer cadeia de caracteres e o booleano falso.

A sintaxe de expressões é:

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

Para entender o que significa cada símbolo na sintaxe de expressões, consulte a tabela a seguir:

Símbolo Definição
attribute_name Qualquer propriedade do documento JSON na coleção FROM.
binary_operator Qualquer operador binário listado na seção Operadores.
function_name Qualquer função listada na seção Funções.
decimal_literal Um float expresso em notação decimal.
hexadecimal_literal Um número expresso pela cadeia de caracteres '0x' seguido por uma cadeia de caracteres de dígitos hexadecimais.
string_literal São cadeias de caracteres Unicode representadas por uma sequência de zero ou mais caracteres Unicode ou sequências de escape. As literais de cadeia de caracteres são colocadas entre aspas simples ou aspas duplas. Escapes permitidos: \', \", \\, \uXXXX para caracteres Unicode definidos por quatro dígitos hexadecimais.

Operadores

Há suporte para os seguintes operadores:

Família Operadores
Aritmético +, -, *, /, %
Lógico AND, OR, NOT
Comparação =, !=, <, >, <=, >=, <>

Funções

Ao consultar gêmeos e trabalhos, a única função com suporte é:

Função Descrição
IS_DEFINED(propriedade) Retorna um valor booliano que indica se um valor foi atribuído à propriedade (incluindo null).

Em condições de rotas, há suporte para as seguintes funções matemáticas:

Função Descrição
ABS(x) Retorna o valor absoluto (positivo) da expressão numérica especificada.
EXP(x) Retorna o valor exponencial da expressão numérica especificada (e^x).
POWER(x,y) Retorna o valor da expressão especificada para a potência indicada (x^y).
SQUARE(x) Retorna o quadrado do valor numérico especificado.
CEILING(x) Retorna o menor valor de número inteiro maior ou igual à expressão numérica especificada.
FLOOR(x) Retorna o maior inteiro menor ou igual à expressão numérica especificada.
SIGN(x) Retorna o sinal positivo (+1), zero (0) ou negativo (-1) da expressão numérica especificada.
SQRT(x) Retorna a raiz quadrada do valor numérico especificado.

Em condições de rotas, há suporte para as seguintes funções de verificação de tipo e conversão de tipo:

Função Descrição
AS_NUMBER Converte a cadeia de caracteres de entrada em um número. noop se a entrada for um número; Undefined se a cadeia de caracteres não representar um número.
IS_ARRAY Retorna um valor booliano que indica se o tipo da expressão especificada é uma matriz.
IS_BOOL Retorna um valor booliano que indica se o tipo da expressão especificada é um booliano.
IS_DEFINED Retorna um valor booliano que indica se um valor foi atribuído à propriedade. Essa função só tem suporte quando o valor é um tipo primitivo. Os tipos primitivos incluem cadeia de caracteres, booliano, numérico ou null. Não há suporte para DateTime, tipos de objeto e matrizes.
IS_NULL Retorna um valor booliano que indica se o tipo da expressão especificada é nulo.
IS_NUMBER Retorna um valor booliano que indica se o tipo da expressão especificada é um número.
IS_OBJECT Retorna um valor booliano que indica se o tipo da expressão especificada é um objeto JSON.
IS_PRIMITIVE Retorna um valor booleano indicando se o tipo da expressão especificada é um primitivo (cadeia de caracteres, booliano, numérico ou null).
IS_STRING Retorna um valor booliano que indica se o tipo da expressão especificada é uma cadeia de caracteres.

Em condições de rotas, há suporte para as seguintes funções de cadeias de caracteres:

Função Descrição
CONCAT(x, y, …) Retorna uma cadeia de caracteres que é o resultado da concatenação de dois ou mais valores de cadeia de caracteres.
LENGTH(x) Retorna o número de caracteres da expressão de cadeia de caracteres especificada.
LOWER(x) Retorna uma expressão de cadeia de caracteres depois de converter dados de caracteres maiúsculos em minúsculos.
UPPER(x) Retorna uma expressão de cadeia de caracteres depois de converter dados de caracteres minúsculos em maiúsculos.
SUBSTRING(cadeia de caracteres, início [, tamanho]) Retorna parte de uma expressão de cadeia de caracteres começando na posição baseada em zero do caractere especificado e continua até o comprimento especificado ou até o final da cadeia de caracteres.
INDEX_OF (cadeia de caracteres, fragmento) Retorna a posição inicial da primeira ocorrência da segunda expressão de cadeia de caracteres dentro da primeira expressão de cadeia de caracteres especificada, ou -1 quando a cadeia de caracteres não é encontrada.
STARTSWITH(x, y) Retorna um valor booliano que indica se a primeira expressão de cadeia de caracteres começa com a segunda.
ENDSWITH(x, y) Retorna um valor booliano que indica se a primeira expressão de cadeia de caracteres termina com a segunda.
CONTAINS(x,y) Retorna um valor booliano que indica se a primeira expressão de cadeia de caracteres contém a segunda.

Exemplos de consulta com os SDKs de serviço

Exemplo de C#

A funcionalidade da consulta é exposta pelo SDK do serviço de C# na classe RegistryManager.

Aqui está um exemplo de uma consulta simples:

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

O objeto de consulta é instanciado com os parâmetros mencionados na seção paginação de resultados da consulta. Em seguida, várias páginas são recuperadas chamando os métodos GetNextAsTwinAsync várias vezes.

Exemplo do Node.js

A funcionalidade de consulta é exposta pelo SDK do serviço IoT do Azure para Node.js no objeto Registry.

Aqui está um exemplo de uma consulta simples:

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

O objeto de consulta é instanciado com os parâmetros mencionados na seção paginação de resultados da consulta. Várias páginas são recuperadas chamando o método nextAsTwin várias vezes.

Próximas etapas