Elasticsearch地理边界框查询(geo_bounding_box)详解

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_leftbottom_right定义边界框外,还可以使用以下方式:

  1. 使用top_rightbottom_left组合
  2. 单独指定四个边界值:
"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(默认):如果字段未映射则抛出异常

精度注意事项

地理数据的精度是有限的,在索引和查询时都会进行舍入处理:

  1. 索引时地理点总是向下舍入
  2. 查询时边界框的上边界向下舍入,下边界向上舍入
  3. 纬度误差小于4.20e-8度,经度误差小于8.39e-8度(赤道处小于1cm)

对于地理形状数据,由于舍入原因:

  • 边界框底部和左侧边缘的形状可能不匹配查询
  • 稍微超出边界框顶部和右侧边缘的形状仍可能匹配查询

实际应用建议

  1. 数据预处理:在索引前确保地理数据的准确性,考虑可能的舍入误差
  2. 边界框定义:根据数据特点选择最合适的边界框定义方式
  3. 性能优化:对于大量地理数据查询,考虑使用地理索引优化查询性能
  4. 误差处理:在应用层处理可能的边界匹配误差,特别是对精度要求高的场景

地理边界框查询是Elasticsearch地理空间功能的重要组成部分,合理使用可以高效解决许多基于地理位置的数据筛选需求。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值