读书笔记《elasticsearch-blueprints》使用Geo增强搜索的趣味性
首先,我们需要查看数据的各个方面并围绕 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
网格中包含两个餐厅,而所有其他网格每个包含一个。
先前聚合的图形表示将如下图所示: