使用 Kibana 将地理空间数据输入 Elasticsearch,以便在 ES|QL 中使用

如何使用 Kibana 和 csv 摄取处理器将地理空间数据摄取到 Elasticsearch 中,以便在 Elasticsearch 查询语言 (ES|QL) 中进行搜索。Elasticsearch 具有强大的地理空间搜索功能,ES|QL 将大幅提高易用性和 OGC 熟悉度。但要使用这些功能,我们需要地理空间数据。

使用单一解决方案观察、保护和搜索数据。从应用程序监控到威胁检测,Kibana是您用于关键用例的多功能平台。立即开始 14 天免费试用

我们最近发布了一篇博客,介绍了如何使用 Elasticsearch 新的强大 管道式查询语言 ES|QL 中 的新 地理空间搜索 功能 。要使用这些功能,您需要在 Elasticsearch 中保存地理空间数据。因此,在本博客中,我们将向您展示如何获取地理空间数据,以及如何在 ES|QL 查询中使用这些数据。

使用 Kibana 导入地理空间数据

我们在上一篇博客的示例中使用的数据是基于我们内部用于集成测试的数据。为方便起见,我们在此以 CSV 文件的形式提供了这些信息,您可以使用 Kibana 轻松导入这些信息。数据包括机场、城市和城市边界。您可以从以下网址下载数据

您可以猜到,我们花了一些时间将这些数据源合并到上述两个文件中,目的是测试 ES|QL 的地理空间特性。这可能与您的具体数据需求不尽相同,但希望这能让您对可能的情况有所了解。我们特别想展示几件有趣的事情:

  • 将包含地理空间字段的数据与其他可索引数据一起导入
  • 同时导入geo_pointgeo_shape 数据并在查询中一起使用
  • 将数据导入可使用空间关系连接的两个索引中
  • 创建摄取管道以促进未来的导入(超越 Kibana)
  • 摄取处理器的一些示例,如csvconvertsplit

虽然我们将在本博客中讨论 如何 使用 CSV 数据,但重要的是要了解 使用 Kibana 添加地理数据的 几种方法 。在地图应用程序中,您可以上传 CSV、GeoJSON 和 ESRI ShapeFiles 等分隔数据,还可以直接在地图中绘制图形。在本博客中,我们将重点介绍从 Kibana 主页导入 CSV 文件。

导入机场

第一个文件是airports.csv、我们需要处理一些有趣的怪癖。首先,列之间有额外的空白分隔,这不是 CSV 文件的典型特征。其次,type 字段是一个多值字段,我们需要将其分割成不同的字段。最后,有些字段不是字符串,需要转换为正确的类型。所有这些都可以使用 Kibana 的 CSV 导入功能来完成。

从 Kibana 主页开始。有一个名为"添加集成入门" 的部分,其中有一个名为"上传文件" 的链接:

点击该链接,您将进入"Upload file" 页面。在此,您可以拖放airports.csv 文件,Kibana 将分析该文件并为您提供数据预览。它应该会自动检测到分隔符是逗号,第一行是标题行。但是,假设所有字段都是textkeyword ,它可能没有修剪列之间多余的空白,也没有确定字段的类型。我们需要解决这个问题。

单击Override settings 并选中Should trim fields 复选框 ,然后Apply 关闭设置。现在,我们需要确定字段的类型。可在下一页查看,请点击Import

首先选择一个索引名称,然后选择Advanced ,进入字段映射和摄取处理器页面。

在此,我们需要对索引的字段映射和导入数据的摄取管道进行更改。首先,虽然 Kibana 可能会将scalerank 字段自动检测为long ,但却误将locationcity_location 字段视为keyword 。将它们编辑为geo_point ,最后得到类似的映射:

您在这里有一定的灵活性,但要注意的是,您选择的类型会影响字段的索引方式和可能的查询类型。例如,如果将location 设置为keyword ,则无法对其执行任何地理空间搜索查询。同样,如果将elevation 设置为text ,则无法对其执行数值范围查询。

现在是修复摄取管道的时候了。如果 Kibana 自动检测到scalerank 如上所示long ,它还会添加一个处理器,将字段转换为long 。我们需要为elevation 字段添加一个类似的处理器,这次将其转换为double 。编辑管道,确保您已将此转换到位。在保存之前,我们还需要进行一次转换,将type 字段分成多个字段。在管道中添加split 处理器,配置如下

最终的摄取管道应该是这样的

请注意,我们没有为locationcity_location 字段添加转换处理器。这是因为字段映射中的geo_point 类型已经了解这些字段中数据的WKT格式。geo_point 类型可以理解一系列格式,包括WKT、GeoJSON 等。例如,如果我们在 CSV 文件中有latitudelongitude 两列,我们就需要添加scriptset 处理器,将这两列合并为一个geo_point 字段(例如。"set": {"field": "location", "value": "{{lat}},{{lon}}"}).

现在我们可以导入文件了。点击Import ,数据就会按照我们刚刚定义的映射和摄取管道导入索引。如果在摄取数据时出现任何错误,Kibana 会在这里报告,这样你就可以编辑源数据或摄取管道,然后再试一次。

请注意,新的摄取管道已经创建。可进入 Kibana 的Stack Management 部分,选择Ingest pipelines 查看。在这里,您可以看到我们刚刚创建的管道,如有必要,还可以对其进行编辑。事实上,Ingest pipelines 部分可用于创建和测试摄取管道,如果你计划进行更复杂的摄取,这是一项非常有用的功能。

如果您想立即探索这些数据,请跳到后面的章节,但如果您还想导入城市边界,请继续阅读。

导入城市边界

与前一个示例相比,airport_city_boundaries.csv中的城市边界文件导入更为简单。它包含一个city_boundary 字段和一个city_location 字段,前者是城市边界的 WKT 表示法,如POLYGON ,后者是城市位置的geo_point 表示法。我们可以用与机场数据类似的方式导入这些数据,但有一些不同之处:

  • 我们需要选择覆盖设置Has header row ,因为这不是自动检测到的
  • 我们不需要修剪字段,因为数据中已经没有多余的空白了
  • 由于所有类型都是字符串或空间类型,因此我们无需编辑采集管道
  • 不过,我们必须编辑字段映射,将city_boundary 字段设置为geo_shape ,将city_location 字段设置为 geo_point

我们最终的字段映射如下

与之前的airports.csv 导入一样,只需单击Import 即可将数据导入索引。数据将通过我们编辑的映射和 Kibana 定义的摄取管道导入。

使用开发工具探索地理空间数据

在 Kibana 中,通常使用"Discover" 探索索引数据。不过,如果您打算使用 ES|QL 查询编写自己的应用程序,尝试访问原始 Elasticsearch API 可能会更有趣。Kibana 有一个方便的控制台,可用于尝试编写查询。这就是所谓的Dev Tools 控制台,可以在 Kibana 侧边栏中找到。该控制台直接与 Elasticsearch 集群对话,可用于运行查询、创建索引等。

试试以下方法:

结果如下

距离缩写名字位置国家城市标高
273418.05776847183火腿汉堡点 (10.005647830925 53.6320011640866)德国诺德施泰特17.0
337534.653466062TXL柏林泰格尔国际机场点 (13.2903090925074 52.5544287044101)德国霍恩诺恩多夫38.0
483713.15032266214OSL奥斯陆加德尔莫尼点 (11.0991032762581 60.1935783171386)挪威奥斯陆208.0
522538.03148094116BMABromma点(17.9456175406145 59.3555902065112)瑞典斯德哥尔摩15.0
522538.03148094116ARN阿尔兰达点 (17.9307299016916 59.6511203397372)瑞典斯德哥尔摩38.0
624274.8274399083DUS杜塞尔多夫国际机场点 (6.76494446612174 51.2781820420774)德国杜塞尔多夫45.0
633388.6966435644PRG鲁兹恩点 (14.2674849854076 50.1076511703671)捷克布拉格381.0
635911.1873311149AMS史基浦机场点 (4.76437693232812 52.3089323889822)荷兰霍夫多尔普-3.0
670864.137958866法国法兰克福国际机场点 (8.57182286907608 50.0506770895207)德国法兰克福111.0
683239.2529970079WAW奥克西国际机场点 (20.9727263383587 52.171026749259)波兰Piaseczno111.0

使用 Kibana 地图可视化地理空间数据

Kibana 地图是可视化地理空间数据的强大工具。它可用于创建具有多个图层的地图,每个图层代表不同的数据集。数据可以通过各种方式进行过滤、汇总和样式化。在本节中,我们将向您展示如何使用上一节导入的数据在 Kibana 地图中创建地图。

在 Kibana 菜单中,导航至Analytics->Maps ,打开新的地图视图。单击Add Layer ,选择Documents ,选择数据视图airports ,然后编辑图层样式,使用elevation 字段为标记着色,这样我们就可以很容易地看到每个机场的高度。

单击 "保持更改 "保存地图:

现在添加第二个图层,这次选择airport_city_boundaries 数据视图。这次,我们将使用city_boundary 字段对图层进行样式设置,并将填充颜色设为淡蓝色。这将在地图上显示城市边界。确保对图层重新排序,以确保机场标记位于顶部。

空间连接

ES|QL 不支持JOIN 命令,但可以使用ENRICH 命令实现连接的特殊情况。该命令的操作类似于 SQL 中的 "左连接",允许您根据两个数据集之间的空间关系,用另一个索引中的数据来丰富一个索引的结果。

例如,我们可以通过查找包含机场位置的城市边界,用机场服务城市的附加信息来丰富机场表的结果,然后对结果进行一些统计:

如果不先准备 enrich 索引就运行该查询,将会收到类似的错误信息:

如前所述,这是因为 ES|QL 不支持真正的JOIN 命令。其中一个重要原因是 Elasticsearch 是一个分布式系统,而连接是一种昂贵的操作,很难扩展。不过,ENRICH 命令的效率相当高,因为它利用了专门编制的在整个集群中复制的丰富索引,从而可以在每个节点上执行本地连接。

为了更好地理解这一点,让我们把重点放在上面查询中的ENRICH 命令上:

该命令指示 Elasticsearch 丰富从airports 索引中获取的结果,并在原始索引的city_location 字段和airport_city_boundaries 索引的city_boundary 字段之间执行intersects 连接,我们在前面的几个示例中使用了该连接。但其中一些信息在该查询中并不清晰。我们看到的是丰富策略的名称city_boundaries ,缺失的信息被封装在该策略定义中。

在这里我们可以看到,它将执行geo_match 查询(intersects 是默认值),要匹配的字段是city_boundary ,而enrich_fields 是我们要添加到原始文档中的字段。其中一个字段region 实际上被用作STATS 命令的分组键,如果没有这种 "左连接 "功能,我们是做不到这一点的。有关 enrich 策略的更多信息,请参阅enrich 文档

Elasticsearch 中的丰富索引和策略最初是为在索引时使用另一个准备好的丰富索引中的数据来丰富数据而设计的。不过,在 ES|QL 中,ENRICH 命令在查询时工作,不需要使用摄取管道。这实际上使它与 SQLLEFT JOIN 非常相似,只是不能连接任何两个索引,只能在左侧连接一个普通索引,在右侧连接一个专门编制的丰富索引。

无论在哪种情况下,无论是用于摄取管道还是在 ES|QL 中使用,都有必要执行一些准备步骤来设置丰富索引和策略。上文我们已经导入了airport_city_boundaries 索引,但在ENRICH 命令中,它不能直接用作丰富索引。我们首先需要执行两个步骤:

  • 创建上述丰富策略,以定义源索引、源索引中要匹配的字段以及匹配后要返回的字段。
  • 执行该策略可创建丰富索引。这将建立一个特殊的内部索引,将原始源索引读取到一个更高效的数据结构中,并在整个集群中复制。

可以使用以下命令创建丰富策略:

可以使用以下命令执行该策略:

请注意,如果您更改了airport_city_boundaries 索引的内容,则需要重新执行该策略,才能在丰富索引中看到更改的内容。现在,让我们再次运行原始 ES|QL 查询:

这将返回拥有最多机场的前 5 个区域,以及所有匹配区域机场的中心点和这些区域内城市边界的 WKT 表示长度范围:

中心点计数地区
点(-12.13908685930073331.024386116624648)126无效
点(-83.1039831787347842.300230911932886)3底特律
点 (39.74537850357592 47.21613017376512)3городской округ Батайск
点(-156.8098678719252320.476673701778054)3夏威夷
点(-73.9451533276587740.70366442203522)3纽约市
点(-83.1039831787347842.300230911932886)3底特律
点(-76.6687301918864324.306286952923983)2新普罗维登斯
点 (-3.0252167768776417 51.39245774131268)2加的夫
点(-115.4099348466843432.73126147687435)2墨西卡利市
点 (41.790108773857355 50.302146775648)2Центральный район
点(-73.8890273217111845.57078813901171)2蒙特利尔

您可能还会注意到,最常见的地区是null 。这意味着什么?回想一下,我曾将此命令比作 SQL 中的 "左连接",也就是说,如果没有为某个机场找到匹配的城市边界,则仍会返回该机场,但airport_city_boundaries 索引中的字段值为null 。结果发现,有 125 个机场没有找到匹配的city_boundary ,有一个机场找到了匹配的region 字段,但该字段是null 。这样就统计出了 126 个机场,结果中没有region 。如果您的用例要求所有机场都能与城市边界相匹配,那就需要获取更多数据来填补空白。有必要确定两件事:

  • airport_city_boundaries 索引中哪些记录没有city_boundary 字段
  • airports 索引中哪些记录与ENRICH 命令不匹配(即"......")。不相交)

在 Kibana 地图中使用 ES|QL 获取地理空间数据

Kibana 在地图应用程序中添加了对空间 ES|QL 的支持。这意味着您现在可以使用 ES|QL 在 Elasticsearch 中搜索地理空间数据,并在地图上将结果可视化。

在添加图层菜单中有一个新的图层选项,名为"ES|QL" 。与迄今为止介绍的所有地理空间功能一样,该功能在"技术预览版" 中。选择该选项可根据 ES|QL 查询结果在地图上添加图层。例如,您可以在地图上添加一个图层,显示世界上所有的机场。

或者您也可以添加一个图层,显示airport_city_boundaries 索引中的多边形,或者更好的办法是使用上面那个复杂的ENRICH 查询,生成每个地区有多少个机场的统计数据?

后续工作计划

上一篇地理空间搜索博客主要介绍了使用ST_INTERSECTS 等函数进行搜索的方法,Elasticsearch 自 8.14 版起提供了这些功能。本博客将向您展示如何导入我们用于这些搜索的数据。不过,Elasticsearch 8.15 提供了一个特别有趣的功能:ST_DISTANCE ,可用于执行高效的空间距离搜索,这将是下一篇博客的主题!

相关内容

准备好打造最先进的搜索体验了吗?

足够先进的搜索不是一个人的努力就能实现的。Elasticsearch 由数据科学家、ML 操作员、工程师以及更多和您一样对搜索充满热情的人提供支持。让我们联系起来,共同打造神奇的搜索体验,让您获得想要的结果。

亲自试用