Lenguaje de consulta de IoT Hub para dispositivos y módulos gemelos, trabajos y enrutamiento de mensajes

IoT Hub proporciona un lenguaje eficaz de tipo SQL para recuperar información con respecto a los dispositivos gemelos, módulos gemelos, trabajos y enrutamiento de mensajes. Este artículo presenta:

  • una introducción a las características principales del lenguaje de consulta de IoT Hub y
  • una descripción más detallada del lenguaje. Para más información acerca del lenguaje de consulta del enrutamiento de mensajes, consulte Consultas en el enrutamiento de mensajes.

Para ver ejemplos específicos, consulte Consultas para dispositivos y módulos gemelos o Consultas para trabajos.

Nota

Algunas de las características que se mencionan en este artículo, como la mensajería de la nube al dispositivo, los dispositivos gemelos y la administración de dispositivos, solo están disponibles en el nivel estándar de IoT Hub. Para obtener más información sobre los niveles Básico y Estándar o Gratis de IoT Hub, consulte Elección del nivel adecuado de IoT Hub para la solución.

Ejecución de consultas IoT Hub

Las consultas se pueden ejecutar directamente en IoT Hub en Azure Portal.

  1. Inicie sesión en Azure Portal y vaya a IoT Hub.
  2. Seleccione Consultas en la sección Administración de dispositivos del menú de navegación.
  3. Escriba una consulta en el cuadro de texto y seleccione Ejecutar consulta.

También puede ejecutar consultas en las aplicaciones mediante las API de servicio y SDK de servicios IoT de Azure.

Para ver ejemplos de consultas IoT Hub que implementan código, consulte la sección Ejemplos de consultas con los SDK de servicio.

Si desea ver vínculos a ejemplos y páginas de referencia del SDK, vaya a SDK de Azure IoT.

Conceptos básicos de una consulta de IoT Hub

Cada consulta de IoT Hub consta de las cláusulas SELECT y FROM, además de las cláusulas opcionales WHERE y GROUP BY.

Las consultas se ejecutan en una colección de documentos JSON, por ejemplo, dispositivos gemelos. La cláusula FROM indica la colección de documentos en la que se va a iterar (devices, devices.modules o devices.jobs).

Después se aplica el filtro en la cláusula WHERE. Con agregaciones, los resultados de este paso se agrupan según se especifique en la cláusula GROUP BY. Para cada grupo, se genera una fila de acuerdo con lo especificado en la cláusula SELECT.

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

Cláusula SELECT

La cláusula SELECT <select_list> es necesaria en todas las consultas IoT Hub. Especifica qué valores se recuperan de la consulta. Especifica los valores JSON que se usarán para generar nuevos objetos JSON. Para cada elemento del subconjunto filtrado (y, opcionalmente, agrupado) de la colección FROM, la fase de proyección genera un nuevo objeto JSON. Este objeto se construye con los valores especificados en la cláusula SELECT.

Por ejemplo:

  • Devolver todos los valores

    SELECT *
    
  • Devolver propiedades específicas

    SELECT DeviceID, LastActivityTime
    
  • Agregar los resultados de una consulta para devolver un recuento

    SELECT COUNT() as TotalNumber
    

Actualmente, las cláusulas de selección distintas a SELECT solo se admiten en las consultas agregadas de dispositivos gemelos.

La sintaxis siguiente es la gramática de la 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 hace referencia a cualquier propiedad del documento JSON en la colección FROM.

Cláusula FROM

La cláusula FROM <from_specification> es necesaria en todas las consultas de ioT Hub. Debe ser uno de estos tres valores:

  • dispositivos para consultar dispositivos gemelos
  • devices.modules para consultar módulos gemelos
  • devices.jobs para consultar los detalles del trabajo por dispositivo

Por ejemplo:

  • Recuperación de todos los dispositivos gemelos

    SELECT * FROM devices
    

WHERE, cláusula

La cláusula WHERE <condición_del_filtro> es opcional. Especifica una o varias condiciones que los documentos JSON en la colección FROM deben satisfacer para incluirse como parte del resultado. Cualquier documento JSON debe evaluar las condiciones especificadas como "true" para que se incluya en el resultado.

Por ejemplo:

  • Recuperación de todos los trabajos que tienen como destino un dispositivo específico

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

Las condiciones permitidas se describen en la sección expresiones y condiciones.

Cláusula GROUP BY

La cláusula GROUP BY<group_specification> es opcional. Esta cláusula se ejecuta después del filtro especificado en la cláusula WHERE y antes de la proyección especificada en la cláusula SELECT. Agrupa los documentos según el valor de un atributo. Estos grupos se usan para generar valores agregados, como se especifica en la cláusula SELECT.

Por ejemplo:

  • Devolución del recuento de dispositivos que notifican todos los estados de configuración de telemetría

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

Actualmente, solo se admite la cláusula GROUP BY al consultar dispositivos gemelos.

Precaución

En la actualidad, el término group se trata en las consultas como si fuera una palabra clave especial. Si utiliza group como un nombre de propiedad, considere la posibilidad de incluirlo entre corchetes dobles para evitar errores; por ejemplo, SELECT * FROM devices WHERE tags.[[group]].name = 'some_value'.

La sintaxis formal de GROUP BY es:

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

Attribute_name hace referencia a cualquier propiedad del documento JSON en la colección FROM.

Paginación de resultados de la consulta

Se crea una instancia de un objeto de consulta con un tamaño máximo de página menor o igual que 100 registros. Para obtener varias páginas, llame al método nextAsTwin en el SDK de Node.js o GetNextAsTwinAsync en el método de SDK de .Net varias veces. El objeto de consulta puede exponer varios valores Next, en función de la opción de deserialización que requiera la consulta. Por ejemplo, un objeto de consulta puede devolver objetos de trabajo o dispositivos gemelos, o JSON sin formato si se usan proyecciones.

Expresiones y condiciones

Brevemente, una expresión:

  • Se evalúa como una instancia de tipo JSON (como booleano, número, cadena, matriz u objeto).
  • Se define manipulando datos procedentes del documento JSON del dispositivo y constantes mediante funciones y operadores integrados.

Las condiciones son expresiones que se evalúan como un valor booleano. Cualquier constante distinta al booleano true se considera como false. Esta regla incluye null, undefined, cualquier instancia de objeto o matriz, cualquier cadena y el valor booleano false.

La sintaxis de las expresiones 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 comprender lo que significa cada símbolo en la sintaxis de expresiones, consulte la tabla siguiente:

Símbolo Definición
attribute_name Cualquier propiedad del documento JSON en la colección FROM.
binary_operator Cualquier operador binario que figure en la sección Operadores.
function_name Cualquier función que figure en la sección Funciones.
decimal_literal Un valor float expresado en notación decimal.
hexadecimal_literal Un número expresado por la cadena "0x" seguido de una cadena de dígitos hexadecimales.
string_literal Las cadenas Unicode representadas por una secuencia de cero o varios caracteres Unicode o secuencias de escape. Los literales de cadena se cierran entre comillas simples o dobles. Caracteres de escape permitidos: \', \", \\, \uXXXX para los caracteres Unicode definidos con cuatro dígitos hexadecimales.

Operadores

Se admiten los siguientes operadores:

Familia Operadores
Aritméticos +, -, *, /, %
Lógicos AND, OR, NOT
De comparación =, !=, <, >, <=, >=, <>

Functions

Cuando se consultan gemelos y trabajos, la única función admitida es:

Función Descripción
IS_DEFINED(property) Devuelve un valor booleano que indica si se ha asignado un valor a la propiedad (incluido null).

En condiciones de rutas, se admiten las siguientes funciones matemáticas:

Función Descripción
ABS(x) Devuelve el valor absoluto (positivo) de la expresión numérica especificada.
EXP(x) Devuelve el valor exponencial de la expresión numérica especificada (e^x).
POWER(x,y) Devuelve el valor de la expresión especificada a la potencia especificada (x^y).
SQUARE(x) Devuelve el cuadrado del valor numérico especificado.
CEILING(x) Devuelve el valor entero más pequeño mayor o igual que la expresión numérica especificada.
FLOOR(x) Devuelve el entero más grande que sea menor o igual que la expresión numérica especificada.
SIGN(x) Devuelve el signo positivo (+1), cero (0) o negativo (-1) de la expresión numérica especificada.
SQRT(x) Devuelve la raíz cuadrada del valor numérico especificado.

En condiciones de rutas, se admiten las funciones de conversión y comprobación de tipos siguientes:

Función Descripción
AS_NUMBER Convierte la cadena de entrada en un número. noop si la entrada es un número; Undefined si la cadena no representa un número.
IS_ARRAY Devuelve un valor booleano que indica si el tipo de la expresión especificada es una matriz.
IS_BOOL Devuelve un valor booleano que indica si el tipo de la expresión especificada es un valor booleano.
IS_DEFINED Devuelve un valor booleano que indica si se ha asignado un valor a la propiedad. Esta función solo se admite cuando el valor es de tipo primitivo. Los tipos primitivos son cadena, booleano, numérico o null. No se admiten los valores DateTime, los tipos de objeto ni las matrices.
IS_NULL Devuelve un valor booleano que indica si el tipo de la expresión especificada es nulo.
IS_NUMBER Devuelve un valor booleano que indica si el tipo de la expresión especificada es un número.
IS_OBJECT Devuelve un valor booleano que indica si el tipo de la expresión especificada es un objeto JSON.
IS_PRIMITIVE Devuelve un valor booleano que indica si el tipo de la expresión especificada es un tipo primitivo (cadena, booleano, numérico o null).
IS_STRING Devuelve un valor booleano que indica si el tipo de la expresión especificada es una cadena.

En condiciones de rutas, se admiten las siguientes funciones de cadena:

Función Descripción
CONCAT(x, y, …) Devuelve una cadena que es el resultado de concatenar dos o más valores de cadena.
LENGTH(x) Devuelve el número de caracteres de la expresión de cadena especificada.
LOWER(x) Devuelve una expresión de cadena después de convertir los datos de caracteres en mayúsculas a minúsculas.
UPPER(x) Devuelve una expresión de cadena después de convertir datos de caracteres en minúsculas a mayúsculas.
SUBSTRING(string, start [, length]) Devuelve parte de una expresión de cadena a partir de la posición de base cero del carácter especificado y continúa hasta la longitud especificada, o hasta el final de la cadena.
INDEX_OF(string, fragment) Devuelve la posición inicial de la primera aparición de la expresión de la segunda cadena dentro de la primera expresión de cadena especificada, o -1 si no se encuentra la cadena.
STARTSWITH(x, y) Devuelve un valor booleano que indica si la primera expresión de cadena empieza con la segunda.
ENDSWITH(x, y) Devuelve un valor booleano que indica si la primera expresión de cadena finaliza con la segunda.
CONTAINS(x,y) Devuelve un valor booleano que indica si la primera expresión de cadena contiene la segunda.

Ejemplos de consultas con los SDK de servicio

Ejemplo de C#

El SDK del servicio C# expone la funcionalidad de consulta en la clase RegistryManager.

Este ejemplo se corresponde a una consulta 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
    }
}

Se crea una instancia del objeto de consulta con los parámetros mencionados en la sección paginación de resultados de la consulta. Después, se recuperan diversas páginas con varias llamadas a los métodos GetNextAsTwinAsync.

Ejemplo de Node.js

El SDK de servicios IoT de Azure para Node.js expone la funcionalidad de consulta en el objeto Registry.

Este ejemplo se corresponde a una consulta 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);

Se crea una instancia del objeto de consulta con los parámetros mencionados en la sección paginación de resultados de la consulta. Después, se recuperan diversas páginas con varias llamadas al método nextAsTwin.

Pasos siguientes