Elasticsearch地理边界框查询(geo_bounding_box)详解
什么是地理边界框查询
地理边界框查询(geo_bounding_box)是Elasticsearch提供的一种地理空间查询方式,用于查找与指定矩形区域相交的地理点(geo_point)或地理形状(geo_shape)数据。这种查询在需要基于地理范围筛选数据时非常有用,例如:
- 查找某个城市区域内的所有商店
- 筛选出特定矩形区域内的用户位置
- 查询与某个地理边界框相交的地理形状
基本用法示例
准备测试数据
首先我们需要创建包含地理数据的索引。以下是创建两个索引的示例,一个存储地理点数据,另一个存储地理形状数据:
PUT /my_locations
{
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
}
}
PUT /my_locations/_doc/1
{
"pin": {
"location": {
"lat": 40.12,
"lon": -71.34
}
}
}
PUT /my_geoshapes
{
"mappings": {
"properties": {
"pin": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
}
}
PUT /my_geoshapes/_doc/1
{
"pin": {
"location": {
"type" : "polygon",
"coordinates" : [[[13.0 ,51.5], [15.0, 51.5], [15.0, 54.0], [13.0, 54.0], [13.0 ,51.5]]]
}
}
}
执行边界框查询
定义边界框需要指定两个对角点的坐标。以下是查询地理点数据的示例:
GET my_locations/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
对于地理形状数据,查询语法相同:
GET my_geoshapes/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
}
}
}
}
}
边界框定义方式
Elasticsearch提供了多种定义边界框的方式,开发者可以根据实际情况选择最适合的格式。
1. 经纬度属性格式
"pin.location": {
"top_left": {
"lat": 40.73,
"lon": -74.1
},
"bottom_right": {
"lat": 40.01,
"lon": -71.12
}
}
2. 经纬度数组格式
按照[经度, 纬度]的顺序排列,符合GeoJSON规范:
"pin.location": {
"top_left": [ -74.1, 40.73 ],
"bottom_right": [ -71.12, 40.01 ]
}
3. 经纬度字符串格式
使用"纬度,经度"的字符串格式:
"pin.location": {
"top_left": "40.73, -74.1",
"bottom_right": "40.01, -71.12"
}
4. WKT(Well-Known Text)格式
"pin.location": {
"wkt": "BBOX (-74.1, -71.12, 40.73, 40.01)"
}
5. Geohash格式
"pin.location": {
"top_left": "dr5r9ydj2y73",
"bottom_right": "drj7teegpus6"
}
高级用法与注意事项
顶点定义方式
除了使用top_left和bottom_right定义边界框外,还可以使用以下方式:
- 使用
top_right和bottom_left组合 - 单独指定四个边界值:
"pin.location": {
"top": 40.73,
"left": -74.1,
"bottom": 40.01,
"right": -71.12
}
处理未映射字段
当查询多个可能有不同映射的索引时,可以使用ignore_unmapped选项:
{
"geo_bounding_box": {
"pin.location": {
"top_left": "40.73, -74.1",
"bottom_right": "40.01, -71.12"
},
"ignore_unmapped": true
}
}
true:忽略未映射字段,不匹配任何文档false(默认):如果字段未映射则抛出异常
精度注意事项
地理数据的精度是有限的,在索引和查询时都会进行舍入处理:
- 索引时地理点总是向下舍入
- 查询时边界框的上边界向下舍入,下边界向上舍入
- 纬度误差小于4.20e-8度,经度误差小于8.39e-8度(赤道处小于1cm)
对于地理形状数据,由于舍入原因:
- 边界框底部和左侧边缘的形状可能不匹配查询
- 稍微超出边界框顶部和右侧边缘的形状仍可能匹配查询
实际应用建议
- 数据预处理:在索引前确保地理数据的准确性,考虑可能的舍入误差
- 边界框定义:根据数据特点选择最合适的边界框定义方式
- 性能优化:对于大量地理数据查询,考虑使用地理索引优化查询性能
- 误差处理:在应用层处理可能的边界匹配误差,特别是对精度要求高的场景
地理边界框查询是Elasticsearch地理空间功能的重要组成部分,合理使用可以高效解决许多基于地理位置的数据筛选需求。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



