Compartir vía


Análisis de datos JSON y Avro en Azure Stream Analytics

El servicio Azure Stream Analytics admite el procesamiento de eventos en formatos de datos CSV, JSON y Avro. Tanto los datos JSON como los datos Avro se pueden estructurar y contener algunos tipos complejos, tales como objetos anidados (registros) y matrices.

Tipos de datos de registro

Los tipos de datos de registro se utilizan para representar las matrices JSON y Avro cuando se usan los formatos correspondientes en los flujos de datos de entrada. Estos ejemplos muestran un sensor de ejemplo, que lee los eventos de entrada en formato JSON. Este es el ejemplo de un solo evento:

{
    "DeviceId" : "12345",
    "Location" :
    {
        "Lat": 47,
        "Long": 122
    },
    "SensorReadings" :
    {
        "Temperature" : 80,
        "Humidity" : 70,
        "CustomSensor01" : 5,
        "CustomSensor02" : 99,
        "SensorMetadata" : 
        {
        "Manufacturer":"ABC",
        "Version":"1.2.45"
        }
    }
}

Acceso a campos anidados en un esquema conocido

Use la notación de puntos (.) para acceder a los campos anidados directamente desde la consulta. Por ejemplo, esta consulta selecciona las coordenadas de latitud y longitud de la propiedad Location en los datos JSON anteriores. Use la notación de puntos para navegar por varios niveles, como se muestra en el siguiente fragmento de código:

SELECT
    DeviceID,
    Location.Lat,
    Location.Long,
    SensorReadings.Temperature,
    SensorReadings.SensorMetadata.Version
FROM input

El resultado es el siguiente:

|DeviceID|Lat|Long|Temperature|Version|
|-|-|-|-|-|
|12345|47|122|80|1.2.45|

Selección de todas las propiedades

Puede seleccionar todas las propiedades de un registro anidado mediante el carácter comodín. Considere el ejemplo siguiente:

SELECT
    DeviceID,
    Location.*
FROM input

El resultado es el siguiente:

|DeviceID|Lat|Long|
|-|-|-|
|12345|47|122|

Acceso a los campos anidados cuando el nombre de la propiedad es una variable

Use la función GetRecordPropertyValue si el nombre de la propiedad es una variable. Esta función le ayuda a crear consultas dinámicas sin codificar nombres de propiedad de forma fija.

Por ejemplo, imagine que el flujo de datos de ejemplo tiene que combinarse con datos de referencia que contienen los umbrales de cada sensor de dispositivo. En el siguiente fragmento se muestra un ejemplo de estos datos de referencia.

{
    "DeviceId" : "12345",
    "SensorName" : "Temperature",
    "Value" : 85
},
{
    "DeviceId" : "12345",
    "SensorName" : "Humidity",
    "Value" : 65
}

El objetivo es unir el conjunto de datos de ejemplo de la parte superior del artículo a esos datos de referencia y generar un evento para cada medida del sensor por encima de su umbral. Esta combinación significa que el evento único puede generar varios eventos de salida si varios sensores están por encima de sus respectivos umbrales. Para conseguir resultados similares sin una combinación, consulte el siguiente ejemplo:

SELECT
    input.DeviceID,
    thresholds.SensorName,
    "Alert: Sensor above threshold" AS AlertMessage
FROM input      -- stream input
JOIN thresholds -- reference data input
ON
    input.DeviceId = thresholds.DeviceId
WHERE
    GetRecordPropertyValue(input.SensorReadings, thresholds.SensorName) > thresholds.Value

GetRecordPropertyValue selecciona la propiedad de SensorReadings que coincide con el nombre de propiedad procedente de los datos de referencia. A continuación, extrae el valor asociado de SensorReadings.

El resultado es el siguiente:

|DeviceID|SensorName|AlertMessage|
| - | - | - |
| 12345 | Humidity | Alert: Sensor above threshold |

Conversión de campos de registro en eventos independientes

Para convertir los campos de registro en eventos independientes, use el operador APPLY con la función GetRecordProperties.

Mediante el uso de los datos de ejemplo originales, puede usar la siguiente consulta para extraer propiedades en diferentes eventos:

SELECT
    event.DeviceID,
    sensorReading.PropertyName,
    sensorReading.PropertyValue
FROM input as event
CROSS APPLY GetRecordProperties(event.SensorReadings) AS sensorReading

El resultado es el siguiente:

|DeviceID|SensorName|AlertMessage|
|-|-|-|
|12345|Temperature|80|
|12345|Humidity|70|
|12345|CustomSensor01|5|
|12345|CustomSensor02|99|
|12345|SensorMetadata|[object Object]|

Mediante WITH, puede enrutar esos eventos a distintos destinos:

WITH Stage0 AS
(
    SELECT
        event.DeviceID,
        sensorReading.PropertyName,
        sensorReading.PropertyValue
    FROM input as event
    CROSS APPLY GetRecordProperties(event.SensorReadings) AS sensorReading
)

SELECT DeviceID, PropertyValue AS Temperature INTO TemperatureOutput FROM Stage0 WHERE PropertyName = 'Temperature'
SELECT DeviceID, PropertyValue AS Humidity INTO HumidityOutput FROM Stage0 WHERE PropertyName = 'Humidity'

Análisis de registros JSON en datos de referencia de SQL

Al usar Azure SQL Database como datos de referencia en el trabajo, puede incluir una columna que contenga datos en formato JSON. En el ejemplo siguiente se muestra este formato:

|DeviceID|Data|
|-|-|
|12345|{"key": "value1"}|
|54321|{"key": "value2"}|

Puede analizar el registro JSON en la columna Datos escribiendo una sencilla función de JavaScript definida por el usuario.

function parseJson(string) {
return JSON.parse(string);
}

Para acceder a los campos de los registros JSON, cree un paso en la consulta de Stream Analytics, como se muestra en el ejemplo siguiente.

WITH parseJson as
(
SELECT DeviceID, udf.parseJson(sqlRefInput.Data) as metadata,
FROM sqlRefInput
)

SELECT metadata.key
INTO output
FROM streamInput
JOIN parseJson 
ON streamInput.DeviceID = parseJson.DeviceID

Tipos de datos de matriz

Los tipos de datos de matriz son una colección ordenada de valores. En esta sección se detallan algunas operaciones típicas en los valores de matriz. Estos ejemplos utilizan las funciones GetArrayElement, GetArrayElements, GetArrayLength y el operador APPLY.

Este es un ejemplo de un evento. Tanto como son de tipo matriz:

{
    "DeviceId" : "12345",
    "SensorReadings" :
    {
        "Temperature" : 80,
        "Humidity" : 70,
        "CustomSensor01" : 5,
        "CustomSensor02" : 99,
        "CustomSensor03": [12,-5,0]
     },
    "SensorMetadata":[
        {          
            "smKey":"Manufacturer",
            "smValue":"ABC"                
        },
        {
            "smKey":"Version",
            "smValue":"1.2.45"
        }
    ]
}

Trabajar con un elemento de matriz específico

Seleccione el elemento de matriz en un índice especificado (seleccione el primer elemento de matriz):

SELECT
    GetArrayElement(SensorReadings.CustomSensor03, 0) AS firstElement
FROM input

El resultado es el siguiente:

|firstElement|
|-|
|12|

Selección de la longitud de matriz

SELECT
    GetArrayLength(SensorReadings.CustomSensor03) AS arrayLength
FROM input

El resultado es el siguiente:

|arrayLength|
|-|
|3|

Conversión de los elementos de matriz en eventos independientes

Seleccione todos los elementos de matriz como eventos individuales. El operador APPLY junto con la función integrada GetArrayElements extrae todos los elementos de matriz como eventos individuales:

SELECT
    DeviceId,
	CustomSensor03Record.ArrayIndex,
	CustomSensor03Record.ArrayValue
FROM input
CROSS APPLY GetArrayElements(SensorReadings.CustomSensor03) AS CustomSensor03Record

El resultado es el siguiente:

|DeviceId|ArrayIndex|ArrayValue|
|-|-|-|
|12345|0|12|
|12345|1|-5|
|12345|2|0|
SELECT   
    i.DeviceId,	
    SensorMetadataRecords.ArrayValue.smKey as smKey,
    SensorMetadataRecords.ArrayValue.smValue as smValue
FROM input i
CROSS APPLY GetArrayElements(SensorMetadata) AS SensorMetadataRecords

El resultado es el siguiente:

|DeviceId|smKey|smValue|
|-|-|-|
|12345|Manufacturer|ABC|
|12345|Version|1.2.45|

Para mostrar los campos extraídos en columnas, gire el conjunto de datos usando la sintaxis WITH junto con la operación JOIN. Esta combinación requiere una condición de límite de tiempo que impide la duplicación:

WITH DynamicCTE AS (
	SELECT   
		i.DeviceId,
		SensorMetadataRecords.ArrayValue.smKey as smKey,
		SensorMetadataRecords.ArrayValue.smValue as smValue
	FROM input i
	CROSS APPLY GetArrayElements(SensorMetadata) AS SensorMetadataRecords 
)

SELECT
	i.DeviceId,
	i.Location.*,
	V.smValue AS 'smVersion',
	M.smValue AS 'smManufacturer'
FROM input i
LEFT JOIN DynamicCTE V ON V.smKey = 'Version' and V.DeviceId = i.DeviceId AND DATEDIFF(minute,i,V) BETWEEN 0 AND 0 
LEFT JOIN DynamicCTE M ON M.smKey = 'Manufacturer' and M.DeviceId = i.DeviceId AND DATEDIFF(minute,i,M) BETWEEN 0 AND 0

El resultado es el siguiente:

|DeviceId|Lat|Long|smVersion|smManufacturer|
|-|-|-|-|-|
|12345|47|122|1.2.45|ABC|

Data Types in Azure Stream Analytics