Elasticsearch 核心技术(十):GEO 地理查询(geo_bounding_box、geo_distance、geo_shape)

news2024/11/26 20:18:42

在这里插入图片描述

❤️ 博客主页:水滴技术
🚀 支持水滴:点赞👍 + 收藏⭐ + 留言💬
🌸 订阅专栏:大数据核心技术从入门到精通

文章目录

  • 一、地理数据类型
    • 1.1、geo_point 地理点类型
      • 1.1.1、创建一个含有 geo_point 字段的索引
      • 1.1.2、通过“对象”指定 geo_point
      • 1.1.3、通过“字符串”指定 geo_point
      • 1.1.4、通过“地理哈希”指定 geo_point
      • 1.1.5、通过“数组”指定 geo_point
      • 1.1.6、通过“WKT”指定 geo_point
    • 1.2、geo_shape 地理形状类型
      • 1.2.1、创建一个含有 geo_shape 字段的索引
      • 1.2.2、通过 Point 指定单个地理坐标
      • 1.2.3、通过 LineString 指定一条线
      • 1.2.4、通过 Polygon 指定一个多边形
      • 1.2.5、通过 MultiPoint 指定多个点
      • 1.2.6、通过 MultiLineString 指定多条线
      • 1.2.7、通过 MultiPolygon 指定多个多边形
      • 1.2.8、通过 GeometryCollection 指定地理形状的集合
      • 1.2.9、通过 envelope 指定矩形或包络线
      • 1.2.10、通过 circle 指定圆形
  • 二、地理查询
    • 2.1、geo_bounding_box 矩形过滤
      • 2.1.1、查询矩形内的定位点(文档)
    • 2.2、geo_distance 距离查询(圆形过滤)
      • 2.2.1、查询“附近的人”
      • 2.2.2、查询“附近的人”并按距离排序
    • 2.3、geo_polygon 多边形查询(已过时)
    • 2.4、geo_shape 地理形状查询
      • 2.4.1、查询 intersects 相交关系
      • 2.4.2、查询 disjoint 不相交关系
      • 2.4.3、查询 within 在...之内关系
      • 2.4.4、查询 contains 包含关系
  • 三、附录
    • 附录一:es_location_001 索引
    • 附录二:es_location_002 索引
    • 附录三:地图工具
  • 系列文章
  • 热门专栏


大家好,我是水滴~~

地理信息查询是 Elasticsearch 的重要特性之一,其 GEO 功能主要用于地理信息的存储和搜索。本篇主要内容:介绍 Elasticsearch 的两种地理数据类型,并通过一些实例来讲述geo_bounding_box 查询、geo_distance 查询和 geo_shape 查询。

一、地理数据类型

在介绍地理查询前,我们先来了解下地理数据类型。Elasticsearch 支持两种地理数据类型:geo_pointgeo_shape。在之前的文章《Elasticsearch 核心技术(五):常用数据类型详解》中有介绍过,学过的友友可以跳过本章节。

注意:Elasticsearch 使用的是 WGS-84 坐标系,如果你是直接从高德地图中获取的经纬度坐标,需要转换一下再存储,否则会有精度问题。当然,如果对精度要求没有那么高,请忽略。

1.1、geo_point 地理点类型

geo_point 数据类型用来存储一个由经纬度组成的地理点,也就是地理坐标。

地理坐标在生活中有很多用处,比如:在一个陌生的城市,可以导航到指定的酒店;点外卖时可以查看附近有哪些好吃的;走累了可以看看哪里有共享单车等等。

1.1.1、创建一个含有 geo_point 字段的索引

下面示例创建一个 index_geo_point 索引,其中 location 字段为 geo_point 类型。

PUT index_geo_point
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}

1.1.2、通过“对象”指定 geo_point

可以通过一个对象来表示地理点,其中 lat 表示纬度,lon 表示经度。

POST index_geo_point/_doc/1
{
  "id": 1,
  "location": { 
    "lat": 39.917846,
    "lon": 116.397058
  }
}

1.1.3、通过“字符串”指定 geo_point

可以通过一个字符串表示地理点,格式为:"lat, lon"

注意:字符串的地理点的顺序为 lat,lon,这与数组和WKT相反。

POST index_geo_point/_doc/2
{
  "id": 2,
  "location": "39.917846, 116.397058"
}

1.1.4、通过“地理哈希”指定 geo_point

可以通过地理点的哈希值来表示地理点。

POST index_geo_point/_doc/3
{
  "id": 3,
  "location": "drm3btev3e86"
}

1.1.5、通过“数组”指定 geo_point

可以通过一个数组来表示地理点,格式为:[lon, lat]

POST index_geo_point/_doc/4
{
  "id": 4,
  "location": [116.397058, 39.917846]
}

1.1.6、通过“WKT”指定 geo_point

可以通过 Well-Known Text 格式的 POINT 来表示地理点,格式为:"POINT(lon, lat)"

POST index_geo_point/_doc/5
{
  "id": 5,
  "location": "POINT(116.397058, 39.917846)"
}

1.2、geo_shape 地理形状类型

geo_shape 数据类型用于存储地理形状,例如:直线、矩形、多边形等。

也有很多场景只使用一个地理点是无法满足的,比如:一所学校、一处旅游景点、一座城市等等,想要表示这样大面积的地点,就需要用到 geo_shape 了。

下面一起看下 geo_shape 类型是如何指定的。

1.2.1、创建一个含有 geo_shape 字段的索引

下面示例创建一个 index_geo_shape 索引,其中 location 字段为 geo_shape 类型。

PUT index_geo_shape
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_shape"
      }
    }
  }
}

1.2.2、通过 Point 指定单个地理坐标

Point 类型用于指定单个地理坐标点,坐标数组格式为:[lon, lat]

POST index_geo_shape/_doc/1
{
  "id": 1,
  "location": {
    "type": "Point",
    "coordinates": [116.397058, 39.917846]
  }
}

1.2.3、通过 LineString 指定一条线

LineString 类型用于指定一条线,该线由两个或多个位置点组成。

POST index_geo_shape/_doc/2
{
  "id": 2,
  "location": {
    "type": "LineString",
    "coordinates": [ [116.397058, 39.917846], [116.397058, 38.111111] ]
  }
}

1.2.4、通过 Polygon 指定一个多边形

Polygon 类型用于指定一个多边形,该多边形要求第一个点和最后一个点必须相同,表示该多边形是闭合的。

POST index_geo_shape/_doc/3
{
  "id": 3,
  "location": {
    "type": "Polygon",
    "coordinates": [
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
    ]
  }
}

这里要注意,coordinates 是一个数组,表示可以指定多个多边形。

下面示例指定了两个多边形,一个数组表示多边形的外部边界,另一个数组表示多边形的内部边界,即表示一个带孔的多边形。

POST index_geo_shape/_doc/4
{
  "id": 4,
  "location" : {
    "type" : "Polygon",
    "coordinates" : [
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
      [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
    ]
  }
}

1.2.5、通过 MultiPoint 指定多个点

MultiPoint 类型用于指定多个点。

POST index_geo_shape/_doc/5
{
  "id": 5,
  "location" : {
    "type" : "MultiPoint",
    "coordinates" : [
      [102.0, 2.0], [103.0, 2.0]
    ]
  }
}

1.2.6、通过 MultiLineString 指定多条线

MultiLineString 类型用于指定多条线。

POST index_geo_shape/_doc/6
{
  "id": 6,
  "location" : {
    "type" : "MultiLineString",
    "coordinates" : [
      [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0] ],
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0] ],
      [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8] ]
    ]
  }
}

1.2.7、通过 MultiPolygon 指定多个多边形

MultiPolygon 类型用于指定多个多边形。

POST index_geo_shape/_doc/7
{
  "id": 7,
  "location" : {
    "type" : "MultiPolygon",
    "coordinates" : [
      [ [[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]] ],
      [ [[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
        [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]] ]
    ]
  }
}

1.2.8、通过 GeometryCollection 指定地理形状的集合

GeometryCollection 类型用于指定一个地理形状的集合,即可以包含多个上面所属的地理形状。

POST index_geo_shape/_doc/8
{
  "id": 8,
  "location" : {
    "type": "GeometryCollection",
    "geometries": [
      {
        "type": "Point",
        "coordinates": [100.0, 0.0]
      },
      {
        "type": "LineString",
        "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
      }
    ]
  }
}

1.2.9、通过 envelope 指定矩形或包络线

envelope 类型用于指定一个矩形或包络线,它由两个坐标组成,分别表示左上角和右下角的坐标。

POST index_geo_shape/_doc/9
{
  "id": 9,
  "location" : {
    "type" : "envelope",
    "coordinates" : [ [100.0, 1.0], [101.0, 0.0] ]
  }
}

1.2.10、通过 circle 指定圆形

circle 类型用于指定一个圆形,需要指定圆心坐标和半径。

注意:映射字段时,圆形不能使用默认的策略,需要将 strategy 指定为 recursive。如下:

PUT index_geo_shape2
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_shape",
        "strategy": "recursive"
      }
    }
  }
}

添加文档时,radius 用于指定半径,如果未指定单位,默认为米

POST index_geo_shape/_doc/10
{
  "id": 10,
  "location" : {
    "type" : "circle",
    "coordinates" : [101.0, 1.0],
    "radius" : "100m"
  }
}

二、地理查询

地理查询主要用于上文讲的两种地理数据类型 geo_pointgeo_shape 的查询,查询的方法包括下面四种:geo_bounding_boxgeo_distancegeo_polygongeo_shape

下面我们分别介绍它们具体的应用。

2.1、geo_bounding_box 矩形过滤

geo_bounding_box 用于查询所有落入矩形的地理点所属文档。查询时需要指定两个坐标点左上角和右下角,这两个点就可以确定一个矩形,而查询的结果为,所有定位点落入该矩形的文档。

下面我们举例说明:

2.1.1、查询矩形内的定位点(文档)

我们以“故宫博物院”为例,取其左上角和右下角的坐标点,会形成一个矩形,然后查询该矩形内的坐标点(所属文档)。

在这里插入图片描述

上图中,故宫的左上角坐标点为 116.391978,39.922561,右下角坐标点为 116.402149,39.913443
另外找了 6 个点,分别代表 6 个文档的位置,它们的坐标点如下:
1:116.39775,39.92029
2:116.395947,39.916208
3:116.410624,39.91871
4:116.397235,39.909823
5:116.385304,39.917591
6:116.396548,39.92832

从肉眼可以看出,1 和 2 号坐标点在故宫的矩形框内,我们通过该实例,看能否准确的查出内容。

我们使用索引 es_location_001 演示该示例,索引的创建,及文档的添加请见附录一,这里我们只讲查询**。**

查询时需要指定 geo_bounding_box 类型,并指定 top_left 左上角的坐标,bottom_right 右下角的坐标。

GET es_location_001/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "location": {
            "top_left": {
              "lat": 39.922561,
              "lon": 116.391978
            },
            "bottom_right": {
              "lat": 39.913443,
              "lon": 116.402149
            }
          }
        }
      }
    }
  }
}

查询结果:通过查询结果可以看出 1、2 文档被查出,正是我们猜测的结果。

{
  "took" : 929,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1,
          "location" : [
            116.39775,
            39.92029
          ]
        }
      },
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "location" : [
            116.395947,
            39.916208
          ]
        }
      }
    ]
  }
}

2.2、geo_distance 距离查询(圆形过滤)

geo_distance 用于查询距离中心点指定范围内的地理点所属文档,也就是圆形过滤。查询时需要指定圆心的坐标,以及半径长度,就可以查询方圆内的文档了。

下面我们举例说明:

2.2.1、查询“附近的人”

我们还是使用 es_location_001 索引那 6 个坐标点来演示,而假设“我”当前的坐标为 116.410539,39.912983,然后看下附近两公里内的人,如下图:

在这里插入图片描述

查询时需要指 geo_distance 并指定定圆心坐标(“我”的位置)和半径距离 distance

GET /es_location_001/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "2km",
          "location": {
            "lat": 39.912983,
            "lon": 116.410539
          }
        }
      }
    }
  }
}

查询结果:通过查询结果可以看出,1、2、3、4个点距离“我”在两公里内。

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1,
          "location" : [
            116.39775,
            39.92029
          ]
        }
      },
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "location" : [
            116.395947,
            39.916208
          ]
        }
      },
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "id" : 3,
          "location" : [
            116.410624,
            39.91871
          ]
        }
      },
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "id" : 4,
          "location" : [
            116.397235,
            39.909823
          ]
        }
      }
    ]
  }
}

2.2.2、查询“附近的人”并按距离排序

上面的示例只显示了查询结果,并没有显示每个“人”距离“我”有多远,也没有排序。下面我们看怎么实现排序的。

在这里插入图片描述

按距离排序,需要在上面查询基础上增加 sort 选项,其中:_geo_distance 为“我”的坐标;order指定 asc 表示由近到远排序;unit 指定 km,表示结果显示的距离单位。

GET /es_location_001/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "2km",
          "location": {
            "lat": 39.912983,
            "lon": 116.410539
          }
        }
      }
    }
  },
  "sort": [
   {
     "_geo_distance": {
       "location": {
         "lat": 39.912983,
         "lon": 116.410539
       },
       "order": "asc",
       "unit": "km"
     }
   }
 ]
}

查询结果:查询结果便是按距离排序的结果,并且返回的 sort 选项为每个“人”距离“我”的距离

{
  "took" : 26,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : null,
        "_source" : {
          "id" : 3,
          "location" : [
            116.410624,
            39.91871
          ]
        },
        "sort" : [
          0.6368510653173584
        ]
      },
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : null,
        "_source" : {
          "id" : 4,
          "location" : [
            116.397235,
            39.909823
          ]
        },
        "sort" : [
          1.187873070108458
        ]
      },
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : null,
        "_source" : {
          "id" : 2,
          "location" : [
            116.395947,
            39.916208
          ]
        },
        "sort" : [
          1.2951412302092007
        ]
      },
      {
        "_index" : "es_location_001",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "id" : 1,
          "location" : [
            116.39775,
            39.92029
          ]
        },
        "sort" : [
          1.360073305586383
        ]
      }
    ]
  }
}

2.3、geo_polygon 多边形查询(已过时)

7.12 版本中已弃用,官方推荐使用 geo_shape

在这里插入图片描述

2.4、geo_shape 地理形状查询

geo_shape 用于查询地理形状的空间关系。例如:与指定地理形状相交、包含、不相交的地理形状等。

而 Elasticsearch 支持四种空间关系:

  • intersects:相交,用于查询所有与指定图形相交的文档。
  • disjoint:不相交,用于查询所有与指定图形不相交的文档。
  • within:在…之内,用于查询所有在指定图形之内的文档。
  • contains:包含,用于查询所有包含指定图形的文档。

下面我们举例说明:

我们先准备三个图形,我用的是矩形,如下图所示。并将它们添加到 es_location_002 索引中,索引的创建,及文档的添加请见附录二。
在这里插入图片描述

2.4.1、查询 intersects 相交关系

如下图,查询与蓝色三角形“相交”的图形有哪些,通过肉眼可以看出,1 和 2 与之相交。

在这里插入图片描述
查询相交的语句:

GET es_location_002/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "Polygon",
              "coordinates": [
      [ [116.382215,39.921606], [116.396892,39.919039], [116.387965,39.912719], [116.382215,39.921606] ]
    ]
            },
            "relation": "intersects"
          }
        }
      }
    }
  }
}

查询结果:1 和 2 图形被查出,验证成功

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.391913,
                  39.922199
                ],
                [
                  116.40187,
                  39.922396
                ],
                [
                  116.402127,
                  39.91318
                ],
                [
                  116.392085,
                  39.913114
                ],
                [
                  116.391913,
                  39.922199
                ]
              ]
            ]
          }
        }
      },
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.378009,
                  39.922199
                ],
                [
                  116.385819,
                  39.92233
                ],
                [
                  116.385819,
                  39.914958
                ],
                [
                  116.378009,
                  39.914958
                ],
                [
                  116.378009,
                  39.922199
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

2.4.2、查询 disjoint 不相交关系

还是刚才的蓝色三角形,查询与蓝色三角形“不相交”的图形有哪些,通过肉眼可以看出,3 与之不相交。

在这里插入图片描述
查询不相交的语句:

GET es_location_002/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "Polygon",
              "coordinates": [
      [ [116.382215,39.921606], [116.396892,39.919039], [116.387965,39.912719], [116.382215,39.921606] ]
    ]
            },
            "relation": "disjoint"
          }
        }
      }
    }
  }
}

查询结果:3 图形被查询,验证成功

{
  "took" : 115,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "id" : 3,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.407105,
                  39.923844
                ],
                [
                  116.417405,
                  39.924437
                ],
                [
                  116.417491,
                  39.912127
                ],
                [
                  116.407277,
                  39.911863
                ],
                [
                  116.407105,
                  39.923844
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

2.4.3、查询 within 在…之内关系

如下图,我画了一个大的蓝色矩形,将 1 和 2 包含在内,那么查询所有在蓝色矩形内的文档,看下 1 和 2 图形能否被查出。

在这里插入图片描述
查询在蓝色矩形之内语句:

GET es_location_002/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "Polygon",
              "coordinates": [
      [ [116.374404,39.92391], [116.404616,39.924108], [116.404359,39.911732], [116.374576,39.911337], [116.374404,39.92391] ]
    ]
            },
            "relation": "within"
          }
        }
      }
    }
  }
}

查询结果:1 和 2 图形被查出

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.391913,
                  39.922199
                ],
                [
                  116.40187,
                  39.922396
                ],
                [
                  116.402127,
                  39.91318
                ],
                [
                  116.392085,
                  39.913114
                ],
                [
                  116.391913,
                  39.922199
                ]
              ]
            ]
          }
        }
      },
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.378009,
                  39.922199
                ],
                [
                  116.385819,
                  39.92233
                ],
                [
                  116.385819,
                  39.914958
                ],
                [
                  116.378009,
                  39.914958
                ],
                [
                  116.378009,
                  39.922199
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

注意:在…之内关系也属于相交关系,通过查询相交的图形,也能查出 1 和 2 图形来。

查询相交语句:

GET es_location_002/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "Polygon",
              "coordinates": [
      [ [116.374404,39.92391], [116.404616,39.924108], [116.404359,39.911732], [116.374576,39.911337], [116.374404,39.92391] ]
    ]
            },
            "relation": "intersects"
          }
        }
      }
    }
  }
}

查询结果:1 和 2 图形被查出

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "id" : 2,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.391913,
                  39.922199
                ],
                [
                  116.40187,
                  39.922396
                ],
                [
                  116.402127,
                  39.91318
                ],
                [
                  116.392085,
                  39.913114
                ],
                [
                  116.391913,
                  39.922199
                ]
              ]
            ]
          }
        }
      },
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.378009,
                  39.922199
                ],
                [
                  116.385819,
                  39.92233
                ],
                [
                  116.385819,
                  39.914958
                ],
                [
                  116.378009,
                  39.914958
                ],
                [
                  116.378009,
                  39.922199
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

2.4.4、查询 contains 包含关系

如下图,在 3 图形内画了一个蓝色的三角形,查询所有包含三角形的文档,看能否将 3 图形查出来。

在这里插入图片描述
查询包含语句:

GET es_location_002/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "Polygon",
              "coordinates": [
      [ [116.41071,39.921014], [116.41483,39.917064], [116.409766,39.915748], [116.41071,39.921014] ]
    ]
            },
            "relation": "contains"
          }
        }
      }
    }
  }
}

输出结果:3 图形被查出来

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "id" : 3,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.407105,
                  39.923844
                ],
                [
                  116.417405,
                  39.924437
                ],
                [
                  116.417491,
                  39.912127
                ],
                [
                  116.407277,
                  39.911863
                ],
                [
                  116.407105,
                  39.923844
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

注意:包含关系也属于相交关系,通过查询相交的图形,也能查出 3 图形来。

查询相交语句:

GET es_location_002/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "Polygon",
              "coordinates": [
      [ [116.41071,39.921014], [116.41483,39.917064], [116.409766,39.915748], [116.41071,39.921014] ]
    ]
            },
            "relation": "intersects"
          }
        }
      }
    }
  }
}

查询结果:同样 3 图形被查询出来

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "es_location_002",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "id" : 3,
          "location" : {
            "type" : "Polygon",
            "coordinates" : [
              [
                [
                  116.407105,
                  39.923844
                ],
                [
                  116.417405,
                  39.924437
                ],
                [
                  116.417491,
                  39.912127
                ],
                [
                  116.407277,
                  39.911863
                ],
                [
                  116.407105,
                  39.923844
                ]
              ]
            ]
          }
        }
      }
    ]
  }
}

三、附录

附录一:es_location_001 索引

创建 es_location_001 索引:

PUT es_location_001
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}

添加 6 个文档:

POST es_location_001/_doc/1
{
  "id": 1,
  "location": [116.39775,39.92029]
}

POST es_location_001/_doc/2
{
  "id": 2,
  "location": [116.395947,39.916208]
}

POST es_location_001/_doc/3
{
  "id": 3,
  "location": [116.410624,39.91871]
}

POST es_location_001/_doc/4
{
  "id": 4,
  "location": [116.397235,39.909823]
}

POST es_location_001/_doc/5
{
  "id": 5,
  "location": [116.385304,39.917591]
}

POST es_location_001/_doc/6
{
  "id": 6,
  "location": [116.396548,39.92832]
}

附录二:es_location_002 索引

创建 es_location_002 索引:

PUT es_location_002
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_shape"
      }
    }
  }
}

添加 3 个矩形文档:

POST es_location_002/_doc/1
{
  "id": 1,
  "location": {
    "type": "Polygon",
    "coordinates": [
      [ [116.378009,39.922199], [116.385819,39.92233], [116.385819,39.914958], [116.378009,39.914958], [116.378009,39.922199] ]
    ]
  }
}

POST es_location_002/_doc/2
{
  "id": 2,
  "location": {
    "type": "Polygon",
    "coordinates": [
      [ [116.391913,39.922199], [116.40187,39.922396], [116.402127,39.91318], [116.392085,39.913114], [116.391913,39.922199] ]
    ]
  }
}

POST es_location_002/_doc/3
{
  "id": 3,
  "location": {
    "type": "Polygon",
    "coordinates": [
      [ [116.407105,39.923844], [116.417405,39.924437], [116.417491,39.912127], [116.407277,39.911863], [116.407105,39.923844] ]
    ]
  }
}

附录三:地图工具

  • 高德坐标拾取器

  • 坐标系转换


系列文章

🔥 Elasticsearch 核心技术(一):Elasticsearch 安装、配置、运行(Windows 版)
🔥 Elasticsearch 核心技术(二):elasticsearch-head 插件安装和使用
🔥 Elasticsearch 核心技术(三):Kibana 安装、配置、运行(Windows 版)
🔥 Elasticsearch 核心技术(四):索引管理、映射管理、文档管理(REST API)
🔥 Elasticsearch 核心技术(五):常用数据类型详解
🔥 Elasticsearch 核心技术(六):内置的 8 种分词器详解 + 代码示例
🔥 Elasticsearch 核心技术(七):IK 中文分词器的安装、使用、自定义字典
🔥 Elasticsearch 核心技术(八):常用 DSL 查询(全文搜索、精确匹配、布尔查询)
🔥 Elasticsearch 核心技术(九):搜索结果处理(分页、排序、指定返回字段、去重、高亮显示)

热门专栏

👍 《Python入门核心技术》
👍 《IDEA 教程:从入门到精通》
👍 《Java 教程:从入门到精通》
👍 《MySQL 教程:从入门到精通》
👍 《大数据核心技术从入门到精通》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/533784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

opencv_c++学习(八)

一、两张图像的像素比较 比较最大最小 最小: min(lnputArray src1, InputArray src2, outputArray dst)最大: max(lnputArray src1, InputArray src2, outputArray dst)src1 :第一个图像矩阵,可以是任意通道数的矩阵。 src2:第二个图像矩…

电源电压过冲

前言: 前段时间突然想起来以前的一个问题,这个问题相信大家也都遇到过,甚至是解决过,或者没解决,也就不了了之,今天这篇文章,主要来讲下这个问题,看完喜欢的欢迎给我留言或者点赞&a…

【Linux】常见指令

🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C专栏:Linux修炼内功基地 家人们更新不易,你们的👍点赞👍和⭐关注⭐…

EasyYapi插件—快速生成API接口文档

EasyYapi插件—快速生成API接口文档 1. 功能 导出http到(Controller注解类) YapiPostmanmarkdown导出RPC到 YapimarkdownCall api调用API接口 注意点: 注释中可以使用module标注模块所属的模块。表示接口会发布到yapi模块下;只…

生存分析利器:Python 中的 Kaplan-Meier Fitter 类详解

KaplanMeierFitter是lifelines库中用于计算生存分析的一个类。使用KaplanMeierFitter类,我们可以对我们的数据进行不同组之间的生存分析,比如根据年龄、性别、治疗手段等分类变量进行分组分析。 该类包含许多方法和属性,其中最常用的是fit()…

FPGA复位信号设计讨论

复位概述 复位作为电子系统中最常见的信号同时也是最重要的信号,它对工程师整体的设计表现有着极大的影响。复位信号可能深刻影响设计的性能表现,功耗,面积等等。对于一个优秀的系统设计,很难不把复位信号当成一个关键信号来设计。…

【车载基础软件 |ASF中间件 系列二】— 国产汽车生态平台ASF的生态框架

本文主要介绍国产基础软件开发平台架构下基于ASF的生态框架。 背景信息 随着E/E架构演进,从最初传统的分布式架构,由独立功能的ECU通过CANLIN等高实时性 总线通讯。诼渐演进到当前分域集中式结合车联网功能的结构,车载以大网逐渐步入了整车电子电器架构之中,除了高实时性…

【AIGC使用教程】论文阅读神器 SciSpace 从注册到体验

欢迎关注【AIGC使用教程】 专栏 【AIGC使用教程】论文阅读神器 SciSpace 从注册到体验 【AIGC使用教程】Microsoft Edge/Bing Chat 注册使用完全指南 【AIGC使用教程】GitHub Copilot 免费注册及在 VS Code 中的安装使用 【AIGC使用教程】GitHub Copilot 免费注册及在 PyCharm …

golang第一个简单项目实战+源码(gin+gorm)

创建项目并新建包 点击file->settings->GOPATH,把当前项目加进GOPATH目录中,然后点击apply, 点击加号完成之后,在左边选择go build 新建数据库 编写配置信息 这里将数据的信息都写在了配置文件里面 dns的内容为&#x…

二叉树概念结构,以及画图加代码分析二叉树遍历,创建,销毁,层序遍历,判断是否完全二叉树等等

二叉树 树的概念及结构树的概念树的相关概念树的表示 二叉树的概念及结构概念特殊的二叉树二叉树性质二叉树的存储结构 二叉树的实现二叉树顺序结构的实现二叉树链式结构的实现二叉树的遍历前序遍历中序遍历后序遍历 二叉树结点数量叶子结点数量求树高求k层结点数量 二叉树创建…

SpringMVC第一阶段:SpringMVC的介绍和使用

1、SpringMVC的概述 Spring MVC框架是一个开源的Java平台,为开发强大的基于JavaWeb应用程序提供全面的基础架构支持,并且使用起来非常简单容易。 Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构,用于开发灵活和松散耦合的Web应用程…

【原创】创建Vue3 ts项目

文章目录 创建Vue3 ts项目工作空间创建vue 项目进入项目目录启动项目 & 停止项目访问成功 创建Vue3 ts项目 工作空间 进入工作空间目录:D:\workspace\vue 创建vue 项目 vue create vt #创建vt项目vue test 选择手动进行配置: 选中下面几个核心…

利用 Mybatis-Plus 的动态数据源实现多数据源配置

目录 一、导入依赖 二、Application.yaml配置文件 三、切换数据源 四、其他方法 4.1 配置多个数据源 4.2 定义Datasource和EntityManager 4.3 在需要使用数据源的地方注入不同的EntityManager 官网:https://baomidou.com/pages/a61e1b/#dynamic-datasource …

vue2实现路由跳转后隐藏底部固定导航栏Tabber的一种方式

在使用vue路由的时候,跳转到某些页面上是不需要展示底部固定的导航栏的,所以在某些特定的页面跳转时候,就需要隐藏底部的导航栏 这里用了一种方式去解决这个问题 1、前提 这里我把底部导航栏做了一个组件的封装,然后在App.vue里…

玩转 LLMs 之基础设施「利刃出鞘」

LLMs 时代已经到来,这个由 ChatGPT 开始的全球化技术浪潮,所经之处,风起云涌。LLMs 之于当下,更像是 iOS 、Android 之于移动互联网时代。开发者沸腾,投资机构争抢,与赛道相关的基础设施建设自然也成为整个…

IOC容器中的核心容器ApplicationContext

文章目录 1 环境准备2 容器2.1 容器的创建方式2.2 Bean的三种获取方式2.3 容器类层次结构2.4 BeanFactory的使用 前面已经完成bean与依赖注入的相关知识学习,接下来我们主要学习的是IOC容器中的核心容器。 这里所说的核心容器,大家可以把它简单的理解为…

聊聊我在三家IT公司的工作经历,C++程序员都在做什么?

我想分享一些关于C程序员工作的经验。我先自我介绍一下:我是一名毕业于普通985大学的程序员,已经工作了5年,但是我曾在三家互联网公司工作过,这些公司都还算是比较有名的互联网公司。 好了,不多说了,进入正…

真题详解(自顶向下)-软件设计(七十六)

真题详解(传引用)-软件设计(七十五)https://blog.csdn.net/ke1ying/article/details/130695214 计算机软件著作权,正确的是_____。 非法进行拷贝、发布或更改软件的人被称为软件盗版者 循环冗余CRC校验,设数据位为k位…

KVM网络管理-创建桥接网络

KVM网络管理-创建桥接网络 分类 网络: nat isolated 接口: bridge 虚拟交换机: linux-bridge(linux) ovs(open-Vswitch) NAT网络拓扑图 仅主机模式网络拓扑图 桥接模式网络拓扑图 在Linux主机上开启vm1,从交换机上把…

第五章 面向对象-6.内部类

内部类 内部类分为: 成员内部类、静态嵌套类、匿名内部类(直接new 抽象类,直接new 接口)$1 $2。 如果是函数式接口,可以使用lambda表达,这样可以避免new 接口产生内部匿名类 内部类仍然是一个独立的类,在…