Ingerir dados geoespaciais no Elasticsearch com o Kibana para uso no ES|QL

Como usar o Kibana e o processador de ingestão CSV para importar dados geoespaciais para o Elasticsearch para uso com pesquisa na Linguagem de Consulta Elasticsearch (ES|QL). O Elasticsearch possui recursos poderosos de busca geoespacial, que agora estão chegando ao ES|QL para uma facilidade de uso drasticamente aprimorada e familiaridade com o OGC. Mas para utilizar essas funcionalidades, precisamos de dados geoespaciais.

Observe, proteja e busque seus dados com uma única solução. Do monitoramento de aplicações à detecção de ameaças, o Kibana é sua plataforma versátil para casos de uso críticos. Inicie sua avaliação gratuita de 14 dias agora mesmo.

Recentemente publicamos um artigo no blog descrevendo como usar os novos recursos de pesquisa geoespacial no ES|QL, a nova e poderosa linguagem de consulta encadeada do Elasticsearch. Para usar esses recursos, você precisa ter dados geoespaciais no Elasticsearch. Neste blog, mostraremos como importar dados geoespaciais e como usá-los em consultas ES|QL.

Importando dados geoespaciais usando o Kibana

Os dados que usamos nos exemplos do blog anterior foram baseados em dados que usamos internamente para testes de integração. Para sua conveniência, incluímos aqui algumas informações em formato CSV que podem ser facilmente importadas usando o Kibana. Os dados são uma mistura de aeroportos, cidades e limites urbanos. Você pode baixar os dados de:

Como você pode imaginar, dedicamos algum tempo a combinar essas fontes de dados nos dois arquivos acima, com o objetivo de poder testar os recursos geoespaciais do ES|QL. Isso pode não ser exatamente o que você precisa em termos de dados, mas espero que lhe dê uma ideia do que é possível. Em particular, queremos demonstrar algumas coisas interessantes:

  • Importação de dados com campos geoespaciais juntamente com outros dados indexáveis.
  • Importar dados geo_point e geo_shape e usá-los em conjunto em consultas
  • Importar dados para dois índices que podem ser unidos usando uma relação espacial.
  • Criar um pipeline de ingestão para facilitar importações futuras (além do Kibana)
  • Alguns exemplos de processadores de ingestão, como csv, convert e split

Embora neste blog abordemos o trabalho com dados CSV, é importante entender que existem várias maneiras de adicionar dados geográficos usando o Kibana. No aplicativo Mapa, você pode carregar dados delimitados, como CSV, GeoJSON e ESRI ShapeFiles, e também pode desenhar formas diretamente no mapa. Neste blog, vamos nos concentrar na importação de arquivos CSV da página inicial do Kibana.

Importando os aeroportos

O primeiro arquivo, airports.csv, Possui algumas peculiaridades interessantes com as quais precisamos lidar. Em primeiro lugar, as colunas possuem espaços em branco adicionais entre si, o que não é típico de arquivos CSV. Em segundo lugar, o campo type é um campo de múltiplos valores, que precisamos dividir em campos separados. Por fim, alguns campos não são strings e precisam ser convertidos para o tipo correto. Tudo isso pode ser feito usando o recurso de importação de CSV do Kibana.

Comece pela página inicial do Kibana. Existe uma seção chamada "Comece adicionando integrações", que possui um link chamado "Carregar um arquivo":

Clique neste link e você será redirecionado para a página "Enviar arquivo". Aqui você pode arrastar e soltar o arquivo airports.csv , e o Kibana analisará o arquivo e apresentará uma pré-visualização dos dados. Deveria ter detectado automaticamente o delimitador como uma vírgula e a primeira linha como a linha de cabeçalho. No entanto, provavelmente não removeu o espaço em branco extra entre as colunas, nem determinou os tipos dos campos, assumindo que todos os campos são text ou keyword. Precisamos resolver isso.

Clique em Override settings e marque a caixa de seleção para Should trim fields e Apply para fechar as configurações. Agora precisamos corrigir os tipos dos campos. Isso está disponível na próxima página, então clique em Import.

Primeiro escolha um nome de índice e, em seguida, selecione Advanced para acessar os mapeamentos de campo e a página do processador de ingestão.

Aqui precisamos fazer alterações tanto no mapeamento de campos do índice quanto no pipeline de ingestão para importar os dados. Em primeiro lugar, embora o Kibana provavelmente tenha detectado automaticamente o campo scalerank como long, ele erroneamente percebeu os campos location e city_location como keyword. Edite-os para geo_point, resultando em mapeamentos que se parecem com algo assim:

Você tem alguma flexibilidade aqui, mas observe que o tipo escolhido afetará a forma como o campo é indexado e os tipos de consultas possíveis. Por exemplo, se você deixar location como keyword não poderá realizar nenhuma consulta de pesquisa geoespacial nele. Da mesma forma, se você deixar elevation como text não poderá executar consultas de intervalo numérico nele.

Agora é hora de corrigir o pipeline de ingestão. Se o Kibana detectou automaticamente scalerank como long acima, ele também terá adicionado um processador para converter o campo em long. Precisamos adicionar um processador semelhante para o campo elevation , desta vez convertendo-o em double. Edite o pipeline para garantir que essa conversão esteja implementada. Antes de salvar isso, queremos mais uma conversão, para dividir o campo type em vários campos. Adicione um processador split ao pipeline, com a seguinte configuração:

O pipeline de ingestão final deve ter a seguinte aparência:

Observe que não adicionamos um processador de conversão para os campos location e city_location . Isso ocorre porque o tipo geo_point no mapeamento de campo já entende o formato WKT dos dados nesses campos. O tipo geo_point pode entender uma variedade de formatos, incluindo WKT, GeoJSON e outros. Se tivéssemos, por exemplo, duas colunas no arquivo CSV para latitude e longitude, precisaríamos adicionar um processador script ou set para combiná-las em um único campo geo_point (por exemplo, "set": {"field": "location", "value": "{{lat}},{{lon}}"}).

Agora estamos prontos para importar o arquivo. Clique em Import e os dados serão importados para o índice com os mapeamentos e o pipeline de ingestão que acabamos de definir. Caso ocorram erros na ingestão dos dados, o Kibana os reportará aqui, para que você possa editar os dados de origem ou o pipeline de ingestão e tentar novamente.

Observe que um novo pipeline de ingestão foi criado. Isso pode ser visualizado indo para a seção Stack Management do Kibana e selecionando Ingest pipelines. Aqui você pode ver o pipeline que acabamos de criar e editá-lo, se necessário. Na verdade, a seção Ingest pipelines pode ser usada para criar e testar pipelines de ingestão, um recurso muito útil se você planeja fazer ingestões ainda mais complexas.

Se você deseja explorar esses dados imediatamente, pule para as seções posteriores, mas se também deseja importar os limites da cidade, continue lendo.

Importando os limites da cidade

O arquivo de limites da cidade disponível em airport_city_boundaries.csv é um pouco mais simples de importar do que o exemplo anterior. Contém um campo city_boundary que é uma representação WKT do limite da cidade como um POLYGON e um campo city_location que é uma representação geo_point da localização da cidade. Podemos importar esses dados de forma semelhante aos dados dos aeroportos, mas com algumas diferenças:

  • Precisávamos selecionar a configuração de substituição Has header row pois ela não foi detectada automaticamente.
  • Não foi necessário remover espaços em branco dos campos, pois os dados já estavam livres de espaços desnecessários.
  • Não foi necessário editar o pipeline de ingestão, pois todos os tipos eram de string ou espaciais.
  • No entanto, tivemos que editar os mapeamentos de campo para definir o campo city_boundary como geo_shape e o campo city_location como . geo_point

Nossos mapeamentos de campo finais ficaram assim:

Assim como na importação airports.csv anterior, basta clicar em Import para importar os dados para o índice. Os dados serão importados com os mapeamentos que editamos e o pipeline de ingestão definido pelo Kibana.

Explorando dados geoespaciais com ferramentas de desenvolvimento

No Kibana, é comum explorar os dados indexados com a opção "Descobrir". No entanto, se sua intenção é escrever seu próprio aplicativo usando consultas ES|QL, pode ser mais interessante tentar acessar a API Elasticsearch diretamente. O Kibana possui um console prático para experimentar a escrita de consultas. Isso é chamado de console Dev Tools e pode ser encontrado na barra lateral do Kibana. Este console se comunica diretamente com o cluster Elasticsearch e pode ser usado para executar consultas, criar índices e muito mais.

Experimente o seguinte:

Isso deverá produzir os seguintes resultados:

distânciaabreviarnomeLocalpaíscidadeelevação
273418.05776847183PRESUNTOHamburgoPONTO (10,005647830925 53,6320011640866)AlemanhaNorderstedt17.0
337534,653466062TXLAeroporto Internacional de Berlim-TegelPONTO (13.2903090925074 52.5544287044101)AlemanhaHohen Neuendorf38,0
483713.15032266214OSLOslo GardermoenPONTO (11.0991032762581 60.1935783171386)NoruegaOslo208,0
522538.03148094116BMABromaPONTO (17,9456175406145 59,3555902065112)SuéciaEstocolmo15.0
522538.03148094116ARNArlandaPONTO (17,9307299016916 59,6511203397372)SuéciaEstocolmo38,0
624274,8274399083DUSAeroporto Internacional de DüsseldorfPONTO (6,76494446612174 51,2781820420774)AlemanhaDüsseldorf45,0
633388,6966435644PRGRuzynPONTO (14,2674849854076 50,1076511703671)República TchecaPraga381,0
635911.1873311149AMSSchipholPONTO (4,76437693232812 52,3089323889822)Países BaixosHoofddorp-3,0
670864.137958866FRAFrankfurt InternacionalPONTO (8,57182286907608 50,0506770895207)AlemanhaFrankfurt111.0
683239,2529970079UAUOkecie Int'lPONTO (20,9727263383587 52,171026749259)PolôniaPiaseczno111.0

Visualizando dados geoespaciais com o Kibana Maps

O Kibana Maps é uma ferramenta poderosa para visualizar dados geoespaciais. Pode ser usado para criar mapas com múltiplas camadas, cada camada representando um conjunto de dados diferente. Os dados podem ser filtrados, agregados e formatados de diversas maneiras. Nesta seção, mostraremos como criar um mapa no Kibana Maps usando os dados que importamos na seção anterior.

No menu do Kibana, navegue até Analytics->Maps para abrir uma nova visualização do mapa. Clique em Add Layer e selecione Documents, escolhendo a visualização de dados airports e editando o estilo da camada para colorir os marcadores usando o campo elevation , para que possamos ver facilmente a altitude de cada aeroporto.

Clique em "Manter alterações" para salvar o mapa:

Agora adicione uma segunda camada, desta vez selecionando a visualização de dados airport_city_boundaries . Desta vez, usaremos o campo city_boundary para estilizar a camada e definiremos a cor de preenchimento para um azul claro. Isso mostrará os limites da cidade no mapa. Certifique-se de reordenar as camadas para garantir que os marcadores do aeroporto fiquem por cima.

Junções espaciais

ES|QL não suporta comandos JOIN , mas você pode realizar um caso especial de junção usando o comando ENRICH . Este comando funciona de forma semelhante a uma 'junção à esquerda' em SQL, permitindo enriquecer os resultados de um índice com dados de outro índice com base em uma relação espacial entre os dois conjuntos de dados.

Por exemplo, vamos enriquecer os resultados de uma tabela de aeroportos com informações adicionais sobre a cidade que eles atendem, encontrando o limite da cidade que contém a localização do aeroporto e, em seguida, realizar algumas análises estatísticas dos resultados:

Se você executar essa consulta sem primeiro preparar o índice de enriquecimento, receberá uma mensagem de erro como esta:

Isso ocorre porque, como mencionamos anteriormente, o ES|QL não suporta comandos JOIN verdadeiros. Um motivo importante para isso é que o Elasticsearch é um sistema distribuído, e as junções são operações custosas e difíceis de escalar. No entanto, o comando ENRICH pode ser bastante eficiente, porque utiliza índices enriquecidos especialmente preparados que são duplicados em todo o cluster, permitindo que junções locais sejam realizadas em cada nó.

Para melhor compreender isso, vamos nos concentrar no comando ENRICH na consulta acima:

Este comando instrui o Elasticsearch a enriquecer os resultados recuperados do índice airports e a realizar uma junção intersects entre o campo city_location do índice original e o campo city_boundary do índice airport_city_boundaries , que usamos em alguns exemplos anteriores. Mas algumas dessas informações não estão claramente visíveis nesta consulta. O que vemos é o nome de uma política de enriquecimento city_boundaries e a informação em falta está encapsulada na definição dessa política.

Aqui podemos ver que ele executará uma consulta geo_match (intersects é o padrão), o campo para comparar é city_boundary e os enrich_fields são os campos que queremos adicionar ao documento original. Um desses campos, o region foi na verdade usado como chave de agrupamento para o comando STATS , algo que não poderíamos ter feito sem essa capacidade de 'junção à esquerda'. Para obter mais informações sobre políticas de enriquecimento, consulte a documentação de enriquecimento.

Os índices e políticas de enriquecimento no Elasticsearch foram originalmente projetados para enriquecer dados no momento da indexação, usando dados de outro índice de enriquecimento já preparado. Em ES|QL, no entanto, o comando ENRICH funciona no momento da consulta e não requer o uso de pipelines de ingestão. Isso efetivamente o torna bastante semelhante a um SQL LEFT JOIN, exceto que você não pode unir quaisquer dois índices, apenas um índice normal à esquerda com um índice enriquecido especialmente preparado à direita.

Em ambos os casos, seja para pipelines de ingestão ou para uso no ES|QL, é necessário executar algumas etapas preparatórias para configurar o índice e a política de enriquecimento. Já importamos o índice airport_city_boundaries acima, mas este não é diretamente utilizável como um índice de enriquecimento no comando ENRICH . Primeiro, precisamos realizar duas etapas:

  • Crie a política de enriquecimento descrita acima para definir o índice de origem, o campo no índice de origem a ser comparado e os campos a serem retornados após a correspondência.
  • Execute esta política para criar o índice de enriquecimento. Isso criará um índice interno especial, lendo o índice de origem original para uma estrutura de dados mais eficiente, que será copiada em todo o cluster.

A política de enriquecimento pode ser criada usando o seguinte comando:

E a política pode ser executada usando o seguinte comando:

Observe que, se você alterar o conteúdo do índice airport_city_boundaries , precisará executar esta política novamente para ver as alterações refletidas no índice enriquecido. Agora, vamos executar a consulta ES|QL original novamente:

Isso retorna as 5 principais regiões com o maior número de aeroportos, juntamente com o centroide de todos os aeroportos que possuem regiões correspondentes e o intervalo de comprimento da representação WKT dos limites das cidades dentro dessas regiões:

centroideContagemregião
PONTO (-12.139086859300733 31.024386116624648)126nulo
PONTO (-83.10398317873478 42.300230911932886)3Detroit
PONTO (39,74537850357592 47,21613017376512)3городской округ Батайск
PONTO (-156,80986787192523 20,476673701778054)3Havaí
PONTO (-73,94515332765877 40,70366442203522)3Cidade de Nova York
PONTO (-83.10398317873478 42.300230911932886)3Detroit
PONTO (-76,66873019188643 24.306286952923983)2Nova Providência
PONTO (-3,0252167768776417 51,39245774131268)2Cardiff
PONTO (-115,40993484668434 32,73126147687435)2Município de Mexicali
PONTO (41,790108773857355 50,302146775648)2Área Central
PONTO (-73,88902732171118 45.57078813901171)2Montreal

Você também pode notar que a região mais comumente encontrada foi null. O que isso poderia implicar? Lembre-se de que comparei este comando a um 'left join' em SQL, o que significa que se nenhum limite de cidade correspondente for encontrado para um aeroporto, o aeroporto ainda será retornado, mas com valores null para os campos do índice airport_city_boundaries . Descobriu-se que havia 125 aeroportos que não encontraram nenhum city_boundary correspondente e um aeroporto com uma correspondência onde o campo region era null. Isso levou a uma contagem de 126 aeroportos sem nenhum region nos resultados. Se o seu caso de uso exigir que todos os aeroportos possam ser associados aos limites de uma cidade, isso exigirá a obtenção de dados adicionais para preencher as lacunas. Seria necessário determinar duas coisas:

  • quais registros no índice airport_city_boundaries não possuem campos city_boundary
  • quais registros no índice airports não correspondem usando o comando ENRICH (ou seja, não se cruzam)

Utilizando ES|QL para dados geoespaciais em mapas do Kibana

O Kibana adicionou suporte para Spatial ES|QL no aplicativo Maps. Isso significa que agora você pode usar o ES|QL para pesquisar dados geoespaciais no Elasticsearch e visualizar os resultados em um mapa.

Existe uma nova opção de camada no menu "Adicionar camadas", chamada "ES|QL". Assim como todos os recursos geoespaciais descritos até agora, este está em "prévia técnica". Selecionar esta opção permite adicionar uma camada ao mapa com base nos resultados de uma consulta ES|QL. Por exemplo, você poderia adicionar uma camada ao mapa que mostrasse todos os aeroportos do mundo.

Ou você poderia adicionar uma camada que mostre os polígonos do índice airport_city_boundaries , ou ainda melhor, que tal aquela consulta complexa ENRICH acima que gera estatísticas de quantos aeroportos existem em cada região?

O que vem a seguir?

O blog anterior sobre pesquisa geoespacial focou no uso de funções como ST_INTERSECTS para realizar pesquisas, disponíveis no Elasticsearch desde a versão 8.14. E este blog mostra como importar os dados que usamos nessas pesquisas. No entanto, o Elasticsearch 8.15 trouxe uma função particularmente interessante: ST_DISTANCE que pode ser usada para realizar pesquisas eficientes de distância espacial, e este será o tema do próximo blog!

Conteúdo relacionado

Pronto para criar buscas de última geração?

Uma pesquisa suficientemente avançada não se consegue apenas com o esforço de uma só pessoa. O Elasticsearch é impulsionado por cientistas de dados, especialistas em operações de aprendizado de máquina, engenheiros e muitos outros que são tão apaixonados por buscas quanto você. Vamos nos conectar e trabalhar juntos para construir a experiência de busca mágica que lhe trará os resultados desejados.

Experimente você mesmo(a)