读书笔记《elasticsearch-blueprints》类似谷歌的网络搜索
第 7 章。使用地理增强搜索
地理点是指地球上某个点的纬度和经度。它上面的每个位置都有自己的唯一的纬度和经度。 Elasticsearch 知道基于地理的点,并允许您在其上执行各种操作。在许多情况下,还需要考虑地理位置组件来获得各种功能。例如,假设您需要搜索附近所有提供中餐的餐馆,或者我需要找到最近的免费出租车。在其他一些情况下,我需要找到特定地理位置所在的状态,以了解我当前所处的位置。
本章的建模使得所有提到的例子都与现实生活中的场景、餐厅搜索相关,以便更好地理解。在这里,我们以根据地理偏好对餐厅进行排序为例。本章涵盖了从简单的案例(例如查找最近的餐馆)到更复杂的案例(例如基于距离对餐馆进行分类)的许多案例。
笔记
Elasticsearch 独特而强大的原因在于,您可以将地理操作与任何其他常规搜索查询结合起来,以产生包含位置数据和查询数据的结果。
餐厅数据建模
首先,我们需要查看数据的各个方面并围绕 JSON 文档对其进行建模,以便 Elasticsearch 理解数据。餐厅有名称、位置信息和评级。为了存储位置信息,Elasticsearch 提供了了解纬度和经度信息的功能,并具有基于它进行搜索的功能。因此,最好使用此功能。
让我们看看如何做到这一点。
首先,让我们看看我们的文档应该是什么样子:
现在,让我们定义相同的模式:
现在让我们 索引索引中的一些文档。这方面的一个例子是上一节中显示的 Tamarind restaurant
数据。我们可以如下索引数据:
同样,我们可以索引任意数量的文档。为方便起见,本章我们只索引了总共五家餐厅。
纬度和经度应该是这种格式。 Elasticsearch 还接受其他两种格式(geohash
和 lat_lon
),但让我们坚持使用这一种。当我们将字段位置映射到类型 geo_point
时,Elasticsearch 知道这些信息的含义以及如何对其采取行动。
当前点与各餐厅的距离值
现在,考虑需要查找用户位置与每家餐厅之间的距离的场景。我们怎样才能达到这个要求?我们可以使用脚本;当前地理坐标被传递给脚本,然后运行查询以查找每个餐厅之间的距离,如以下代码所示。在这里,当前位置以 (1, 2)
的形式给出:
我们在前面的查询中使用了名为 arcDistanceInKm
的函数,它接受地理坐标,然后返回该点与位置之间的距离 对查询感到满意。请注意,计算的距离单位是 公里 (km )。您可能已经注意到前面提到的脚本中 location
前后有一长串引号和双引号。这是标准格式,如果我们不使用它,将导致在处理时返回格式错误。
计算从当前点到过滤后的酒店的距离,并在响应的distance
字段中返回,如下代码所示:
基于距离的餐厅分类
在电子商务解决方案中,要搜索餐厅,您需要增加应用程序的可搜索特性。这意味着,如果我们能够提供前 10 个结果以外的结果的快照,它将增加搜索的可搜索特征。例如,如果我们能够显示有多少餐厅供应印度、泰国或其他美食,它实际上会帮助用户更好地了解结果集。
类似地,如果我们能告诉他们餐厅是在附近、在中距离还是在远处,我们真的可以在餐厅搜索用户体验中拉动和弦,如下图所示:
实现这一点并不难,因为我们有一个叫做距离范围聚合的东西。在这种 聚合类型中,我们可以手工制作我们感兴趣的距离范围,并为每个距离创建一个桶。我们也可以定义我们需要的键名,如下代码所示:
在前面的代码中,我们将餐厅分为三个距离范围,即附近酒店(200米以内)、中距离酒店(200米以内)到 2,000 米)和较远的(大于 2,000 米)。使用 which
将此逻辑转换为 Elasticsearch 查询,我们收到的结果如下:
根据距离聚集餐厅
在前面的 示例中,我们看到了餐馆根据从当前点到三个不同类别的距离进行的聚合。现在,我们可以考虑另一种情况,根据餐馆所属的 geohash 网格对餐馆进行分类。如果用户想要了解餐馆分布的地理情况,这种分类可能是有利的。
以下是基于 geohash 的餐厅聚合代码:
你可以从前面的代码中看到我们使用了geohash聚合,它被命名为DifferentGrids
和这里的精度,设置为6
。 precision
字段值可以在 1
到 12
的范围内变化, 1
是最低的,12
是最高的精度参考。
此外,我们在 DifferentGrids
聚合中使用了另一个名为 restaurants
的聚合。 restaurant
聚合使用 top_hits
查询从 DifferentGrids
聚合,否则只会返回 key
和 doc_count
值。
因此,运行前面的代码会给我们以下结果:
正如我们从响应中看到的,有四个带有key
值的桶,分别是s009
、s01n
、s00x
和 s00p
。这些键值代表餐厅所属的不同 geohash 网格。从前面的结果中,我们可以很明显的说
s009
网格中包含两个餐厅,而所有其他网格每个包含一个。
先前聚合的图形表示将如下图所示:
概括
我们发现 Elasticsearch 可以处理地理点和各种特定于地理的操作。我们在本章中介绍的一些地理特定和地理点操作是搜索附近的餐馆(圆圈内的餐馆),搜索范围内的餐馆(同心圆内的餐馆),搜索城市内的餐馆(矩形内的餐馆) ,在多边形内搜索餐馆,并按邻近度对餐馆进行分类。除此之外,我们还可以使用 Elasticsearch 提供的灵活强大的可视化工具 Kibana,用于基于地理的操作。