ElasticSearch Java API GEO操作(REST命令版)

发布时间 2023-10-18 15:44:33作者: 陆上江南

前言

ElasticSearch支持地理空间数据查询、搜索,提供geo_pointgeo_shape两种地理数据类型。

geo_point用于描述一个或多个地理坐标点,主要用于周边位置查询、边界内搜索点、聚合多个范围内的点等功能。

geo_shape用于描述点线面等多种地理数据,使用GeoJson标准格式描述,可以对这些地理数据做相交、不相交、包含等等地理关系的判断与计算。

新增索引

PUT /my_locations
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      }
    }
  }
}

PUT后边紧跟的就是需要创建的索引名:my_locationsmappings中设置了一个属性name,为text类型。

更新geo类型的mappings

新增两个字段,location字段类型为geo_pointpolygon字段类型为geo_shape

PUT后边紧跟索引名my_locations,加_mapping表示在操作mappings。

PUT /my_locations/_mapping
{
  "properties": {
    "name": {
      "type": "text"
    },
    "location": {
      "type": "geo_point"
    },
    "polygon": {
      "type": "geo_shape"
    }
  }
}

查询修改后的索引

GET my_locations/_mapping
{
  "my_locations":
    "mappings":
      "properties":
        "location":
          "type": "geo_point"  
        },  
        "name":
          "type": "text"  
        },  
        "polygon":
          "type": "geo_shape"  
        }  
      }  
    }  
  }  
}

注意不要在请求体里的body里填{},会报错。

新增geo数据

固有格式就是/索引名/_doc/id,表示添加数据。geo_point支持普通经纬度数组、WKTgeohash格式的地理数据。

三种类型的经纬度格式都是经度在前,纬度在后。

新增经纬度数组类型的地理坐标点数据:

POST /my_locations/_doc/1
{
  "name": "喜茶",
  "location": [
    113.947539,
    22.530122
  ]
}

新增WKT类型的地理坐标点数据:

POST my_locations/_doc/2
{
	"name": "喜茶2",
	"location": "POINT(113.947539 22.530122)"
}

新增geohash类型的地理坐标点数据:

POST my_locations/_doc/3
{
	"name": "喜茶geohash",
	"location": "ws100vqp6p"
}

新增另一个地点

POST my_locations/_doc/4

{
	"name": "平安银行",
	"location": [
		113.945805,
		22.530055
	]
}

距离查询

传入一个坐标原点和相应的距离范围,来搜索范围内是否存在坐标点:

GET my_locations/_search
{
    "query": {
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "500m",
                    "location": [
                        113.948769,22.530063
                    ]
                }
            }
        }
    }
}

其中距离单位参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/api-conventions.html#distance-units
常见的公里为km,米为m,默认是米。

聚合查询

定义一个原点和一组距离范围桶,聚合评估每个文档值与原点的距离。

GET my_locations/_search?size=0&filter_path=aggregations
{
  "aggs": {
    "data_around_city": {
      "geo_distance": {
        "unit": "m",
        "field": "location",
        "origin": "113.94823,22.530143",
        "ranges": [
          {
            "to": 100
          },
          {
            "from": 100,
            "to": 300
          },
          {
            "from": 600,
            "to": 1000
          },
          {
            "from": 1000
          }
        ]
      }
    }
  }
}

地理多边形内的点

传入一个多边形来判断多边形范围内是否有坐标点,使用within方法表示内部。

GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "polygon",
              "relation": "within",
              "coordinates": [
                [
                  [
                    113.942373,
                    22.531399
                  ],
                  [
                    113.955111,
                    22.531432
                  ],
                  [
                    113.953261,
                    22.524538
                  ],
                  [
                    113.940451,
                    22.525991
                  ]
                ]
              ]
            }
          }
        }
      }
    }
  }
}

新增面数据

es支持的另一种地理类型字段为geo_shape,包括点、线、多线、面、多面等常见地理类型数据。支持GeoJsonWKT两种标准的地理数据格式。

为第一个喜茶新增多边形的GeoJson数据:

POST my_locations/_doc/1
{
	"name": "喜茶",
	"location": [
		113.947539,
		22.530122
	],
	"polygon": {
		"type": "envelope",
		"coordinates": [
			[
				113.947248,
				22.530295
			],
			[
				113.94776,
				22.529753
			]
		]
	}
}

为第二个喜茶新增WKT数据

POST my_locations/_doc/2
{
	"name": "喜茶2",
	"location": "POINT(113.947539 22.530122)",
	"polygon": "POLYGON ((113.947305 22.530055, 113.947682 22.530047, 113.947718 22.529788, 113.947341 22.529842, 113.947305 22.530055)) "
}

通过点判断落面

判断传入的点落在是否被包含(contains)在相应的多边形内:

GET my_locations/_search
{
	"query": {
		"bool": {
			"must": {
				"match_all": {}
			},
			"filter": {
				"geo_shape": {
					"polygon": {
						"shape": {
							"type": "point",
							"coordinates": [
								113.947305,
								22.530055
							]
						},
						"relation": "contains"
					}
				}
			}
		}
	}
}

判断面相交

GET my_locations/_search
{
	"query": {
		"bool": {
			"must": {
				"match_all": {}
			},
			"filter": {
				"geo_shape": {
					"polygon": {
						"shape": {
							"type": "polygon",
							"relation": "intersects",
							"coordinates": [
								[
									[
										113.947522,
										22.530091
									],
									[
										113.948169,
										22.529966
									],
									[
										113.948187,
										22.529695
									],
									[
										113.94754,
										22.529707
									]
								]
							]
						}
					}
				}
			}
		}
	}
}

参考

  1. Elasticsearch:Geo Point 和 Geo Shape 查询解释
  2. Elasticsearch地理空间之geo_shape
  3. ES地理范围查询第一讲:Java操作地理位置信息(geo_point)
  4. Elasticsearch 之(53) Java API 基于geo_shape根据坐标查找 坐标落在店铺范围的店铺
  5. Geo queries
  6. 百度地图坐标拾取系统
  7. 在线经纬度转geohash
  8. 百度地图 geohash 可视化工具