(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como expandir arrays com mv-expand em KQL: exemplo

João Barros 12 de July de 2026 5 min de leitura

Em tabelas de telemetria é muito comum encontrar colunas dinâmicas que guardam listas dentro de uma única célula: etiquetas de um evento, IDs de produtos de uma encomenda, códigos de erro. Expandir arrays com mv-expand em KQL transforma cada valor dessa lista numa linha própria, e é isso que permite a seguir filtrar, agrupar e contar como em qualquer tabela normal. Todos os exemplos abaixo podem ser copiados tal e qual para um KQL Queryset, porque criam os dados em memória.

Pré-requisitos

  • Acesso a uma base KQL (Eventhouse no Microsoft Fabric) ou a um cluster de Azure Data Explorer.
  • Um KQL Queryset ou a Web UI do Kusto para escrever consultas.
  • Noções básicas dos operadores where, project e summarize.
  • Não é preciso carregar dados: usamos o operador datatable para criar tabelas de exemplo.

Passo 1: Criar dados de exemplo com datatable

Antes de expandir arrays em KQL, precisamos de uma tabela com uma coluna do tipo dynamic. O operador datatable cria uma tabela temporária, sem tocar na base de dados — perfeito para aprender e testar.

let Eventos = datatable(id:int, utilizador:string, etiquetas:dynamic)
[
    1, "ana",   dynamic(["bi", "fabric"]),
    2, "rui",   dynamic(["kql"]),
    3, "maria", dynamic(["bi", "kql", "azure"])
];
Eventos

O resultado tem 3 linhas. Repare que a coluna etiquetas mostra a lista inteira numa só célula — e é exatamente por isso que não conseguimos, por agora, contar quantas vezes aparece cada etiqueta.

Passo 2: Expandir o array com mv-expand

O operador mv-expand (multi-value expand) pega numa coluna dinâmica e produz uma linha por cada elemento do array. As restantes colunas da linha original são repetidas em cada nova linha.

Eventos
| mv-expand etiquetas

Agora temos 6 linhas: 2 para a "ana", 1 para o "rui" e 3 para a "maria". A coluna etiquetas deixou de conter uma lista e passa a conter um único valor por linha.

Passo 3: Dar um nome e um tipo ao valor expandido

Por omissão, o valor expandido continua a ser do tipo dynamic, o que atrapalha comparações de texto e ordenações. A boa prática é atribuir um nome novo à coluna e converter o tipo com to typeof().

Eventos
| mv-expand etiqueta = etiquetas to typeof(string)
| project id, utilizador, etiqueta

A coluna etiqueta é agora uma string verdadeira. Isto permite escrever, por exemplo, | where etiqueta == "kql" sem surpresas.

Passo 4: Saber a posição de cada valor com with_itemindex

Às vezes a ordem dentro do array tem significado (o primeiro erro, a primeira categoria). A opção with_itemindex devolve o índice de cada elemento, começando em 0.

Eventos
| mv-expand with_itemindex = posicao etiqueta = etiquetas to typeof(string)
| project id, utilizador, posicao, etiqueta
| where posicao == 0

Este exemplo devolve apenas a primeira etiqueta de cada evento — uma forma simples de extrair o valor principal de uma lista.

Passo 5: Expandir um dicionário (property bag)

Uma coluna dynamic também pode guardar um objeto com pares chave/valor. Com kind=array, cada par é expandido para um pequeno array de dois elementos: na posição 0 fica a chave e na posição 1 fica o valor.

let Propriedades = datatable(id:int, props:dynamic)
[
    1, dynamic({"pais": "PT", "plano": "pro"}),
    2, dynamic({"pais": "ES", "plano": "free"})
];
Propriedades
| mv-expand kind = array props
| extend chave = tostring(props[0]), valor = tostring(props[1])
| project id, chave, valor

O resultado é uma tabela longa e estreita, com uma linha por propriedade — o formato ideal para depois pivotar ou filtrar por chave.

Passo 6: Agrupar depois de expandir

Com o array expandido, o summarize volta a ser trivial. Este é o objetivo real da maioria das consultas com mv-expand em KQL: contar quantas vezes cada valor aparece.

Eventos
| mv-expand etiqueta = etiquetas to typeof(string)
| summarize eventos = count() by etiqueta
| order by eventos desc

Deve obter bi e kql com 2 eventos cada, e fabric e azure com 1.

Erro comum: se a coluna for texto (por exemplo, um JSON guardado como string), o mv-expand não a consegue expandir. Converta primeiro com extend lista = todynamic(coluna_texto) e só depois expanda.

Verificar o resultado

Confirme três coisas. Primeiro, o número de linhas: Eventos | mv-expand etiquetas | count deve devolver 6, ou seja, a soma dos tamanhos de todos os arrays. Segundo, o tipo da coluna: adicione | extend t = gettype(etiqueta) e confirme que aparece string (e não array). Terceiro, se estiver a trabalhar com arrays muito grandes, tenha presente que o mv-expand expande até 2048 valores por linha por omissão; pode ajustar esse máximo com a opção limit.

Conclusão

Com mv-expand, to typeof() e with_itemindex já consegue transformar qualquer coluna dinâmica numa tabela plana pronta a agregar. O passo natural a seguir é conhecer o mv-apply, que expande o array, aplica uma subconsulta a cada elemento e volta a agregar — muito útil, por exemplo, para ficar apenas com o maior valor de cada lista. Uma dica final: expanda o mais tarde possível na consulta, depois dos where, porque a expansão multiplica linhas e é aí que a performance se perde. Que colunas dinâmicas tem nos seus dados à espera de serem expandidas?