1、地理坐标点
地理坐标点 是指地球表面可以用经纬度描述的一个点。 地理坐标点可以用来计算两个坐标间的距离,还可以判断一个坐标是否在一个区域中,或在聚合中。
地理坐标点不能被动态映射(dynamic mapping)自动检测,而是需要显式声明对应字段类型为 geo-point
:
PUT /attractions
{
"mappings": {
"restaurant": {
"properties": {
"name": {
"type": "string"
},
"location": {
"type": "geo_point"
}
}
}
}
}
2、经纬度坐标格式
如上例,location
字段被声明为 geo_point
后,我们就可以索引包含了经纬度信息的文档了。经纬度信息的形式可以是字符串、数组或者对象:
地理坐标点用字符串形式表示时是纬度在前,经度在后( "latitude,longitude"
),而数组形式表示时是经度在前,纬度在后( [longitude,latitude]
)—顺序刚好相反。
UT /attractions/restaurant/1
{
"name": "Chipotle Mexican Grill",
"location": "40.715, -74.011"
}
PUT /attractions/restaurant/2
{
"name": "Pala Pizza",
"location": {
"lat": 40.722,
"lon": -73.989
}
}
PUT /attractions/restaurant/3
{
"name": "Mini Munchies Pizza",
"location": [ -73.983, 40.719 ]
}
3、通过地理坐标点过滤
1、geo_bounding_box
这是目前为止最有效的地理坐标过滤器了,因为它计算起来非常简单。 你指定一个矩形的 顶部
, 底部
, 左边界
,和 右边界
,然后过滤器只需判断坐标的经度是否在左右边界之间,纬度是否在上下边界之间:
GET /attractions/restaurant/_search
{
"query": {
"filtered": {
"filter": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 40.8,
"lon": -74.0
},
"bottom_right": {
"lat": 40.7,
"lon": -73.0
}
}
}
}
}
}
}
2、geo_distance
地理距离过滤器( geo_distance
)以给定位置为圆心画一个圆,来找出那些地理坐标落在其中的文档:
1、找出所有与指定点距离在 1km
内的 location
字段。访问 Distance Units 查看所支持的距离表示单位
2、 中心点可以表示为字符串,数组或者(如示例中的)对象。详见 经纬度坐标格式。
GET /attractions/restaurant/_search
{
"query": {
"filtered": {
"filter": {
"geo_distance": {
"distance": "1km",
"distance_type": "plane",
"location": {
"lat": 40.715,
"lon": -73.988
}
}
}
}
}
}
两点间的距离计算,有多种牺牲性能换取精度的算法:
arc
最慢但最精确的是arc
计算方式,这种方式把世界当作球体来处理。不过这种方式的精度有限,因为这个世界并不是完全的球体。plane
plane
计算方式把地球当成是平坦的,这种方式快一些但是精度略逊。在赤道附近的位置精度最好,而靠近两极则变差。sloppy_arc
如此命名,是因为它使用了 Lucene 的SloppyMath
类。这是一种用精度换取速度的计算方式, 它使用 Haversine formula 来计算距离。它比arc
计算方式快 4 到 5 倍,并且距离精度达 99.9%。这也是默认的计算方式。
3、geo_distance_range
是一个环状的,它会排除掉落在内圈中的那部分文档。
指定到中心点的距离也可以换一种表示方式:指定一个最小距离(使用 gt
或者 gte
)和最大距离(使用 lt
和 lte
),就像使用 range
过滤器一样:
GET /attractions/restaurant/_search
{
"query": {
"filtered": {
"filter": {
"geo_distance_range": {
"gte": "1km",
"lt": "2km",
"location": {
"lat": 40.715,
"lon": -73.988
}
}
}
}
}
}
4、geo_polygon
找出落在多边形中的点。 这个过滤器使用代价很大 。当你觉得自己需要使用它,最好先看看 geo-shapes 。
4、按距离排序
检索结果可以按与指定点的距离排序:
GET /attractions/restaurant/_search
{
"query": {
"filtered": {
"filter": {
"geo_bounding_box": {
"type": "indexed",
"location": {
"top_left": {
"lat": 40.8,
"lon": -74.0
},
"bottom_right": {
"lat": 40.4,
"lon": -73.0
}
}
}
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 40.715,
"lon": -73.998
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}
]
}