在当今的环境中,基于位置的服务几乎变得不可或缺,因为它们被集成到了无数的应用程序和服务中,例如导航和共享出行服务、餐厅查找器以及社交网络。这些应用程序利用地理搜索和位置查询,通过地理位置来执行搜索和查询数据。
在这篇文章中,我们将介绍在 SOLR 中作为新功能的地理空间搜索,概述其主要概念和语法,并提供示例和解释以及输出说明。
地理空间搜索 类似于全文检索,因为它需要基于可能包含地理坐标的特定数据集输入查询。对于正在侦察兴趣点、计算距离或在区域内搜索的应用程序来说,这种搜索非常重要。基于位置的查询是一种通过根据地理参数(如坐标和距离)进行过滤以及检索数据来工作的查询。
搜索引擎 Elasticsearch 为地理数据和操作提供了丰富的支持。它提供了一系列地理空间数据类型,并支持多种地理空间查询,如 地理距离、地理边界框、地理位置、地理多边形 和 地理坐标系。
地理空间查询的语法
1. Geo-point 数据类型
使用地理空间中的两个坐标来表示一个地理点:纬度和经度。
{
"location": {
"type": "geo_point"
}
}
2. Geo-distance 查询
查找距离某点指定距离内的文档。
{
"query": {
"geo_distance": {
"distance": "200km",
"location": {
"lat": 40.7128,
"lon": -74.0060
}
}
}
}
3. Geo-bounding Box 查询
查找由左上角和右下角坐标定义的指定矩形内的文档。
{
"query": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
4. Geo-polygon 查询
查找指定多边形内的文档。
{
"query": {
"geo_polygon": {
"location": {
"points": [
{ "lat": 40.73, "lon": -74.1 },
{ "lat": 40.01, "lon": -71.12 },
{ "lat": 41.12, "lon": -71.12 }
]
}
}
}
}
示例及输出解释
示例 1:Geo-distance 查询
假设我们在 Elasticsearch 中保存了餐厅的数据集,每个餐厅的位置坐标都以地理坐标的形式保存。有时我们需要找到距离给定地点最多 10 公里范围内的餐厅。
第 1 步:创建带有 Geo-point 映射的索引
首先,我们需要为位置字段创建一个带有 geo_point 映射的索引。
PUT /restaurants
{
"mappings": {
"properties": {
"name": { "type": "text" },
"location": { "type": "geo_point" }
}
}
}
您可以使用 Kibana Dev Tools 等工具或 Postman 等 REST 客户端将此请求发送到您的 Elasticsearch 服务器。
第 2 步:索引示例数据
接下来,我们将一些示例餐厅数据索引到 Elasticsearch 中。
#### 请求:
POST /restaurants/_doc/1
{
"name": "Central Perk",
"location": { "lat": 40.7128, "lon": -74.0060 }
}
POST /restaurants/_doc/2
{
"name": "Monk‘s Cafe",
"location": { "lat": 40.7306, "lon": -73.9352 }
}
分别发送每个 POST 请求以将文档添加到您的 Elasticsearch 索引中。
第 3 步:执行 Geo-distance 查询
现在,我们执行一个 geo_distance 查询,以查找特定位置 10 公里半径范围内的餐厅。
#### 请求:
GET /restaurants/_search
{
"query": {
"geo_distance": {
"distance": "10km",
"location": {
"lat": 40.7128,
"lon": -74.0060
}
}
}
}
输出解释
该查询返回给定坐标 10 公里半径内的餐厅。结果包含 "Central Perk",因为它位于指定距离内。
#### 输出:
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "restaurants",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {
"name": "Central Perk",
"location": {
"lat": 40.7128,
"lon": -74.0060
}
}
}
]
}
}
示例 2:Geo-bounding Box 查询
我们