Analisar dados JSON e Avro no Azure Stream Analytics
O Azure Stream Analytics suporta o processamento de eventos em formatos de dados CSV, JSON e Avro. Os dados JSON e Avro podem ser estruturados e conter alguns tipos complexos, como objetos aninhados (registos) e matrizes.
Nota
Os ficheiros AVRO criados pela Captura do Hub de Eventos utilizam um formato específico que requer que utilize a funcionalidade de desserializador personalizado . Para obter mais informações, veja Read input in any format using .NET custom deserializers (Ler entradas em qualquer formato com desseriais personalizados .NET).
Tipos de dados de registo
Os tipos de dados de registo são utilizados para representar matrizes JSON e Avro quando os formatos correspondentes são utilizados nos fluxos de dados de entrada. Estes exemplos demonstram um sensor de exemplo, que está a ler eventos de entrada no formato JSON. Eis um exemplo de um único evento:
{
"DeviceId" : "12345",
"Location" :
{
"Lat": 47,
"Long": 122
},
"SensorReadings" :
{
"Temperature" : 80,
"Humidity" : 70,
"CustomSensor01" : 5,
"CustomSensor02" : 99,
"SensorMetadata" :
{
"Manufacturer":"ABC",
"Version":"1.2.45"
}
}
}
Aceder a campos aninhados no esquema conhecido
Utilize a notação de pontos (.) para aceder facilmente a campos aninhados diretamente a partir da consulta. Por exemplo, esta consulta seleciona as coordenadas Latitude e Longitude na propriedade Localização nos dados JSON anteriores. A notação de pontos pode ser utilizada para navegar por vários níveis, conforme mostrado abaixo.
SELECT
DeviceID,
Location.Lat,
Location.Long,
SensorReadings.Temperature,
SensorReadings.SensorMetadata.Version
FROM input
O resultado é:
DeviceID | Lat | Longo | Temperatura | Versão |
---|---|---|---|---|
12345 | 47 | 122 | 80 | 1.2.45 |
Selecionar todas as propriedades
Pode selecionar todas as propriedades de um registo aninhado com o caráter universal "*". Considere o exemplo seguinte:
SELECT
DeviceID,
Location.*
FROM input
O resultado é:
DeviceID | Lat | Longo |
---|---|---|
12345 | 47 | 122 |
Aceder a campos aninhados quando o nome da propriedade é uma variável
Utilize a função GetRecordPropertyValue se o nome da propriedade for uma variável. Isto permite criar consultas dinâmicas sem nomes de propriedades de codificação.
Por exemplo, imagine que o fluxo de dados de exemplo tem de ser associado a dados de referência que contenham limiares para cada sensor de dispositivo. Abaixo, é apresentado um fragmento desses dados de referência.
{
"DeviceId" : "12345",
"SensorName" : "Temperature",
"Value" : 85
},
{
"DeviceId" : "12345",
"SensorName" : "Humidity",
"Value" : 65
}
O objetivo aqui é associar o nosso conjunto de dados de exemplo da parte superior do artigo a esses dados de referência e produzir um evento para cada medida de sensor acima do limiar. Isto significa que o nosso único evento acima pode gerar vários eventos de saída se vários sensores estiverem acima dos respetivos limiares, graças à associação. Para obter resultados semelhantes sem uma associação, veja a secção abaixo.
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 seleciona a propriedade em SensorReadings, que nome corresponde ao nome da propriedade proveniente dos dados de referência. Em seguida, o valor associado do SensorReadings é extraído.
O resultado é:
DeviceID | SensorName | AlertMessage |
---|---|---|
12345 | Humidade | Alerta: Sensor acima do limiar |
Converter campos de registo em eventos separados
Para converter campos de registo em eventos separados, utilize o operador APPLY juntamente com a função GetRecordProperties .
Com os dados de exemplo originais, a seguinte consulta pode ser utilizada para extrair propriedades para diferentes eventos.
SELECT
event.DeviceID,
sensorReading.PropertyName,
sensorReading.PropertyValue
FROM input as event
CROSS APPLY GetRecordProperties(event.SensorReadings) AS sensorReading
O resultado é:
DeviceID | SensorName | AlertMessage |
---|---|---|
12345 | Temperatura | 80 |
12345 | Humidade | 70 |
12345 | CustomSensor01 | 5 |
12345 | CustomSensor02 | 99 |
12345 | SensorMetadata | [objeto objeto] |
Ao utilizar o WITH, é possível encaminhar esses eventos para diferentes 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'
Analisar o registo JSON nos dados de referência do SQL
Ao utilizar SQL do Azure Base de Dados como dados de referência na sua tarefa, é possível ter uma coluna com dados no formato JSON. Apresentamos um exemplo abaixo.
DeviceID | Dados |
---|---|
12345 | {"key": "value1"} |
54321 | {"key": "value2"} |
Pode analisar o registo JSON na coluna Dados ao escrever uma função simples definida pelo utilizador javaScript.
function parseJson(string) {
return JSON.parse(string);
}
Em seguida, pode criar um passo na consulta do Stream Analytics, conforme mostrado abaixo, para aceder aos campos dos seus registos JSON.
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 dados de matriz
Os tipos de dados de matriz são uma coleção ordenada de valores. Algumas operações típicas em valores de matriz são detalhadas abaixo. Estes exemplos utilizam as funções GetArrayElement, GetArrayElements, GetArrayLength e o operador APPLY .
Eis um exemplo de um evento. Ambos CustomSensor03
e SensorMetadata
são de matriz de tipo:
{
"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"
}
]
}
Trabalhar com um elemento de matriz específico
Selecione o elemento de matriz num índice especificado (selecionando o primeiro elemento de matriz):
SELECT
GetArrayElement(SensorReadings.CustomSensor03, 0) AS firstElement
FROM input
O resultado é:
firstElement |
---|
12 |
Selecionar comprimento da matriz
SELECT
GetArrayLength(SensorReadings.CustomSensor03) AS arrayLength
FROM input
O resultado é:
matrizLength |
---|
3 |
Converter elementos de matriz em eventos separados
Selecione todo o elemento de matriz como eventos individuais. O operador APPLY juntamente com a função incorporada GetArrayElements extrai todos os elementos de matriz como eventos individuais:
SELECT
DeviceId,
CustomSensor03Record.ArrayIndex,
CustomSensor03Record.ArrayValue
FROM input
CROSS APPLY GetArrayElements(SensorReadings.CustomSensor03) AS CustomSensor03Record
O resultado é:
DeviceId | MatrizIndex | 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
O resultado é:
DeviceId | smKey | smValue |
---|---|---|
12345 | Fabricante | ABC |
12345 | Versão | 1.2.45 |
Se os campos extraídos precisarem de aparecer em colunas, é possível dinamizar o conjunto de dados com a sintaxe WITH para além da operação JOIN . Essa associação requer uma condição de limite de tempo que impede a duplicação:
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
O resultado é:
DeviceId | Lat | Longo | smVersion | smManufacturer |
---|---|---|---|---|
12345 | 47 | 122 | 1.2.45 | ABC |