在本文中,我们将了解 Elasticsearch 的地理查询、如何设置映射和索引,并提供一些示例来说明如何查询数据。
Elasticsearch 中的地理数据
Elasticsearch 允许你以两种方式表示 GeoData:geo_shape 和 geo_point。
Geo Point 允许你将数据存储为纬度和经度坐标对。 当你要针对点之间的距离过滤数据、在边界框内搜索或使用聚合时,请使用此字段类型。 你可以指定许多超出本文范围的功能和选项。 我们将在这里介绍几个,但你可以在 Elasticsearch 的文档中查看地理边界框、地理距离和地理聚合的选项。
当你拥有表示形状的 GeoData 时,或者当你想要查询形状内的点时,请使用 Geo-Shape。 geo_shape 数据必须以 GeoJSON 格式编码,该格式被转换为表示 Geohash 单元格网格上的长/纬度坐标对的字符串。 由于 Elasticsearch 将形状作为术语进行索引,因此很容易确定形状之间的关系,这些关系可以使用相交、不相交、包含或在查询空间关系运算符中进行查询。更多关于 geohash 的学习,请参阅 “Elasticsearch:理解 Elastic Maps 中的 geohash 及其聚合”。
遗憾的是 geo-point 和 geo-shape 不能一起查询。 例如,如果要获取指定多边形内的所有城市,则不能使用以地理点为索引的城市。 它们必须使用 GeoJSON 中的 “type": “point” 进行索引,并作为 geo-shape 进行索引。
Geo Point 字段类型
geo_point 类型的字段接受经纬度对,可以使用:
- 在 bounding box、中心点一定 distance 内、 polygon 内或 geo_shape 查询内查找地理点。
- 在地理上或按距中心点的距离聚合文档。
- 将距离整合到文档的相关性分数中。
- 按距离对文档进行排序。
Geo point 映射
我们可以使用如下的方式来定义一个带有 geo_point 数据类型的索引:
1. PUT location_index
2. {
3. "mappings": {
4. "properties": {
5. "text" : {
6. "type" : "text"
7. },
8. "location": {
9. "type": "geo_point"
10. }
11. }
12. }
13. }
我们可以用五种不同的方式存储 Geo Point。
Geo point 作为一个对象
对象可以与 lat 和 lon 等属性一起使用。
1. PUT location_index/_doc/1
2. {
3. "text": "Geopoint as an object",
4. "location": {
5. "lat": 41.12,
6. "lon": -71.34
7. }
8. }
Geo Point 作为一个字符串
一个纯字符串,可以使用 “,” 分隔,格式为 lat, lon 。
1. PUT location_index/_doc/2
2. {
3. "text": "Geopoint as a string",
4. "location": "41.12,-71.34"
5. }
Geo Point 作为 Geohash
哈希值用于表示 lat 和 lon 。 有一个在线网站可以这样做:
1. PUT location_index/_doc/3
2. {
3. "text": "Geopoint as a geohash",
4. "location": "drm3btev3e86"
5. }
Geo point 作为数组
坐标可以用数组 [lon, lat] 的形式表示,值为 double 。
1. PUT location_index/_doc/4
2. {
3. "text": "Geopoint as an array",
4. "location": [ -71.34, 41.12 ]
5. }
Geo Point 作为 WKT Point
坐标可以用函数 POINT(lon lat) 的形式表示。
1. PUT location_index/_doc/5
2. {
3. "text": "Geopoint as a WKT POINT primitive",
4. "location" : "POINT (-71.34 41.12)"
5. }
注意:无论地理点以何种格式保存,我们也可以查询其他格式。 但要小心正确定义格式。 不要替换为 lat 和 lon 值。 这可以给出未预先确定的值。
Geo shape 字段类型
geo_shape 数据类型有助于对任意地理形状(例如矩形和多边形)进行索引和搜索。 当被索引的数据或被执行的查询包含形状而不仅仅是点时,应该使用它。
你可以使用 geo_shape 查询使用此类型查询文档。
Geo shape 映射
1. PUT geo_shape_indx
2. {
3. "mappings": {
4. "properties": {
5. "location": {
6. "type": "geo_shape"
7. }
8. }
9. }
10. }
我们有如下的几种方式来存储 geo_shape 数据。
Geo Json 类型 POINT
单个地理坐标。 注意:Elasticsearch 仅使用 WGS-84 坐标。
1. POST geo_shape_indx/_doc/1
2. {
3. "location" : {
4. "type" : "point",
5. "coordinates" : [-77.03653, 38.897676]
6. }
7. }
Geo Json 类型 LINESTRING
给定两个或多个点的任意线。
1. POST geo_shape_indx/_doc/2
2. {
3. "location" : {
4. "type" : "linestring",
5. "coordinates" : [[-77.03653, 38.897676], [-77.009051, 38.889939]]
6. }
7. }
Geo Json 类型 POLYGON
一个封闭的多边形,其首点和末点必须匹配,因此需要 n + 1 个顶点来创建 n 边多边形,并且最少需要 4 个顶点。
1. POST geo_shape_indx/_doc/3
2. {
3. "location" : {
4. "type" : "polygon",
5. "coordinates" : [
6. [ [-77.03653, 38.897676], [-77.03653, 37.897676], [-76.03653, 38.897676], [-77.03653, 38.997676], [-77.03653, 38.897676] ]
7. ]
8. }
9. }
Geo Json 类型 MULTIPOLYGON
一组单独的多边形:
1. POST geo_shape_indx/_doc/4
2. {
3. "location" : {
4. "type" : "MultiPolygon",
5. "coordinates" : [
6. [ [[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]] ],
7. [ [[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
8. [[