1.点与图形

地理位置信息,对于这个功能,目前大多数的中间件基本都已经开始支持,比如MongoDB中就提供了2d和2dsphere索引,redis中提供了geo相关的指令集合。
同样,es中也提供了地理位置相关的功能,包括以下两种数据类型

  1. geo_point:以经纬度形式进行存储,用于存储地理位置坐标点,常用与计算坐标点之间的距离以及点聚合等相关功能
  2. geo_shape:以geojson形式进行存储,用于存储地理位置点、线、图形等。用于计算图形之间的交集以及图形中包含了哪些点等等

接下来开始对两种数据结构详细讲解

2.索引点

geo_point其实相比较于geo_shape更为常用,且用起来更为简单,接下来开始讲解geo_point的使用

建立索引

建立索引时,指定数据类型为geo_point即可。
下面以省份坐标为例,指定location数据类型为geo_point

  1. PUT omission
  2. {
  3. "mappings": {
  4. "properties": {
  5. "name":{
  6. "type": "text",
  7. "analyzer": "ik_max_word"
  8. },
  9. "location":{
  10. "type": "geo_point"
  11. }
  12. }
  13. }
  14. }

存储数据

样例数据准备

接下来准备6个省份的坐标信息,如下图
image.png

  1. 北京:(经度:116.20,纬度:39.56)
  2. 山东:(经度:114.19,纬度:34.22)
  3. 湖北:(经度:108.21,纬度:29.01)
  4. 湖南:(经度:108.47,纬度:24.38)
  5. 云南:(经度:97.31,纬度:21.8)
  6. 新疆:(经度:86.37,纬度:42.45)

    数据存储格式

    es中对于geo_point的数据支持三种数据格式,如下

  7. 字符串形式:以逗号分割,纬度在前,经度在后。示例: “location”: “39.56, 116.20”

  8. Json形式:指定经纬度即可,lat代表纬度,lon代表经度。示例:{“location”:{“lat”:114.19,”lon”:34.22}}
  9. 数组形式:经度在前,纬度在后。示例: “location”: [108.21,29.01]

一定要注意的是,字符串类型纬度在前,经度在后。数组类型经度在前,纬度在后
接下来将上述准备的省份坐标录入索引

  1. PUT omission/_bulk
  2. {"create":{}}
  3. {"name":"北京","location":"39.56, 116.20"}
  4. {"create":{}}
  5. {"name":"山东","location":"34.22, 114.19"}
  6. {"create":{}}
  7. {"name":"湖北","location":{"lat":29.01,"lon":108.21}}
  8. {"create":{}}
  9. {"name":"湖南","location":{"lat":24.38,"lon":108.47}}
  10. {"create":{}}
  11. {"name":"云南","location":[97.31,21.8]}
  12. {"create":{}}
  13. {"name":"新疆","location":[86.37,42.45]}

image.png
如图,录入成功

3.查询点

es中提供了多种对于地理位置信息查询的方法,最常用的包括以下两种

  1. geo_bounding_box:给出矩形的左上和右下点坐标,获取矩形内的点
  2. geo_distance:给出一个点以及最远距离,获取距离圆心点距离在最远距离以内的所有点

接下来详细说明

geo_bounding_box

命令格式

geo_bounding_box命令格式如下

  1. GET omission/_search
  2. {
  3. "query": {
  4. "constant_score": {
  5. "filter": {
  6. "geo_bounding_box": {
  7. "FIELD": {
  8. "top_left": {
  9. "lat": 40.73,
  10. "lon": -74.1
  11. },
  12. "bottom_right": {
  13. "lat": 40.717,
  14. "lon": -73.99
  15. }
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }
  1. FIELD:查询字段
  2. top_left:左上角经纬度坐标
  3. bottom_right:右下角经纬度坐标

    示例

    image.png
    以宁夏为左上角,台湾为右下角,可以获取到山东,湖南,湖北的相关信息
    宁夏坐标点:[104.17,35.14]
    台湾坐标点:[119.18,20.45]
    因此查询表达式如下:

    1. GET omission/_search
    2. {
    3. "query": {
    4. "constant_score": {
    5. "filter": {
    6. "geo_bounding_box": {
    7. "location": {
    8. "top_left": {
    9. "lat": 35.14,
    10. "lon": 104.17
    11. },
    12. "bottom_right": {
    13. "lat": 20.45,
    14. "lon": 119.18
    15. }
    16. }
    17. }
    18. }
    19. }
    20. }
    21. }

    image.png
    如图,返回结果与预期一致

    geo_distance

    命令格式

    1. GET omission/_search
    2. {
    3. "query": {
    4. "constant_score": {
    5. "filter": {
    6. "geo_distance": {
    7. "distance": "100km",
    8. "distance_type": "arc",
    9. "FIELD": {
    10. "lat": 40.73,
    11. "lon": -74.1
    12. }
    13. }
    14. }
    15. }
    16. }
    17. }
  4. FIELD:查询字段以及指定圆心点的经纬度坐标

  5. distance:指定的最远距离,其中距离支持如下单位 :::success

  6. 英里:mi/miles

  7. 码:yd/yards
  8. 英尺:ft/feet
  9. 英寸:in/inch
  10. 公里(千米):km/kilometers
  11. 米:m/meters
  12. 厘米:cm/centimeters
  13. 毫米:mm/millimeters
  14. 海里:NM/nmi/nauticalmiles :::

  15. distance_type:距离计算方式,包括arc和plane两种 :::success

  16. arc:基于球面运算,效率较低但精准度较高。当然也不是完全准确,毕竟地球不是一个圆滑的球

  17. plane:基于平面运算,效率较高但精度较低。在赤道附近的位置精度最好,而靠近两极则变差。 :::

    示例

    已知北京距离其他省份距离信息,从小到大排序如下

  18. 北京-山东距离:411.5km

  19. 北京-湖北距离:1112.3km
  20. 北京-湖南距离:1342km
  21. 北京-云南距离:2200km
  22. 北京-新疆距离:2768.5km

以北京为圆心,获取2000km内的省份,理论上应该返回北京,山东,湖北,以及湖南4个省份

  1. GET omission/_search
  2. {
  3. "query": {
  4. "constant_score": {
  5. "filter": {
  6. "geo_distance": {
  7. "distance": "2000km",
  8. "location": {
  9. "lat": 39.56,
  10. "lon": 116.2
  11. }
  12. }
  13. }
  14. }
  15. }
  16. }

image.png
如图,返回结果符合预期

排序

有的时候,我们不仅仅想要获取响应的坐标点,我们还想要结果根据一定的顺序排序,根据地理位置排序与其他字段排序不同。es中同样提供了根据地理位置排序的功能。同时,基于地理位置排序,es还会返回与期望圆心点之间的距离

命令格式

  1. "sort": [
  2. {
  3. "_geo_distance": {
  4. "FIELD": {
  5. "lat": 40,
  6. "lon": -70
  7. },
  8. "order": "asc",
  9. "unit": "km",
  10. "distance_type": "arc"
  11. }
  12. }
  13. ]
  1. _geo_distance:固定写法枚举值,表明按照坐标点排序
  2. FIELD:排序字段以及中心点经纬度
  3. order:正序还是倒序
  4. unit:距离单位
  5. distance_type:距离计算方式,包括arc和plane两种

    示例

    还是以北京为圆心,获取2000km内的省份,理论上应该返回北京,山东,湖北,以及湖南4个省份以及其与北京的距离

    1. GET omission/_search
    2. {
    3. "query": {
    4. "constant_score": {
    5. "filter": {
    6. "geo_distance": {
    7. "distance": "2000km",
    8. "location": {
    9. "lat": 39.56,
    10. "lon": 116.2
    11. }
    12. }
    13. }
    14. }
    15. },
    16. "sort": [
    17. {
    18. "_geo_distance": {
    19. "location": {
    20. "lat": 39.56,
    21. "lon": 116.2
    22. },
    23. "order": "desc",
    24. "unit": "km",
    25. "distance_type": "plane"
    26. }
    27. }
    28. ]
    29. }

    image.png
    如图,返回结果通过与北京的距离倒序排序,并且sort字段中返回了对应的距离

    注意

    地理坐标过滤器使用代价昂贵 ,所以最好在文档集合尽可能少的场景下使用。
    可以先使用那些简单快捷的过滤器,比如 term 或 range ,来过滤掉尽可能多的文档,最后才交给地理坐标过滤器处理。
    布尔型过滤器 boolfilter 很适合做这件事。它会优先让那些基于“bitset”的简单过滤器(见 关于缓存 )来过滤掉尽可能多的文档,然后依次才是更昂贵的地理坐标过滤器或者脚本类的过滤器。

    4.GeoHash

    什么是geohash

    众所周知,对于地理位置信息,常用的保存格式就是经纬度数组以及geojson。那么有没有这样一种数据结构,可以通过一维的方式来表示地理位置的二维坐标呢?答案是,有
    geohash就是这样一种数据,它通过二分,二进制解析,二进制转10进制以及base32等步骤,将一个经纬度坐标,转成了wx4g0e这样的字符串。而这种类型的字符串,也就是geohash的格式了。通常来说,字符串越长,代表精确度越高
    Geohashes 是一种将经纬度坐标( lat/lon )编码成字符串的方式。这么做的初衷只是为了让地理位置在 url 上呈现的形式更加友好,但现在 geohashes 已经变成一种在数据库中有效索引地理坐标点和地理形状的方式。
    Geohashes 把整个世界分为 32 个单元的格子 —— 4 行 8 列
    换句话说, geohash 的长度越长,它的精度就越高。如果两个 geohashes 有一个共同的前缀— gcpuuz—就表示他们挨得很近。共同的前缀越长,距离就越近。
    这也意味着,两个刚好相邻的位置,可能会有完全不同的 geohash 。比如,伦敦 Millenium Dome 的 geohash 是 u10hbp ,因为它落在了 u 这个单元里,而紧挨着它东边的最大的单元是 g 。

    geohash的算法

    首先要明确知道的两点

  6. 经度的范围:-180~180

  7. 纬度的范围:-90~90

接下来开始演示,如何讲一个经纬度坐标转化为一个geohash。

  1. 已知坐标点:北京:(经度:116.20,纬度:39.56)

    经纬度转2进制

  2. 将经纬度范围2分,分为正区间与负区间,

  3. 每次判定目标值所在区间,正区间标1,负区间标0
  4. 之后对所在区间继续2分,
  5. 精度越大,2分的次数越多
  6. 规定上如果长度为2,那么要计算5次2分

计算经度:最终2进制数=11010(PS:正常来说geoHash长度=4要算10次,时间宝贵,这里只做演示)

0区间 1区间 坐标对应区间 2进制值 坐标
-180,0 0,180 1区间 1 116.20
0,90 90,180 1区间 1 116.20
90,135 135,180 0区间 0 116.20
90,112.5 112.5,135 1区间 1 116.20
112.5,123,75 123,75,135 0区间 0 116.20

计算纬度:最终2进制数=10111(PS:正常来说geoHash长度=4要算10次,时间宝贵,这里只做演示)

0区间 1区间 坐标对应区间 2进制值 坐标
-90,0 0,90 1区间 1 39.56
0,45 45,90 0区间 0 39.56
0,22.5 22.5,45 1区间 1 39.56
22.5,33,75 33.75,45 1区间 1 39.56
33.75.39.375 39.375,45 1区间 1 39.56

经纬度2进制数整合

整合原则:奇数位为纬度,偶数位为经度
因此上述经纬度组合后:1101101110

2进制数转10进制

转化原则:5个一组,转为10进制。(PS:为什么是5个一组?因为最后一步要计算base32对应,因此最大数为31,也就是5位2进制数)
因此上述2进制转换后:27,14

base32计算10进制数

对照表如下:
image.png
因此上述10进制转换后:vf
最终计算完成,北京:(经度:116.20,纬度:39.56)转换为geohash后变为vf

上图说话

可能上述的算法还不是很直观,接下来用图解来形象的描述geohash的算法
image.png
如图

  1. 将世界地图的一部分按照4 行 8 列划分成了32块,将设左上角第一块标注为a
  2. 此时对于左上角第一块再进行4 行 8 列划分,再取其左上角第一块,标注为b
  3. ……依次递归,经度越高,划分的块越小。最终拼接得到的字符串越长,经度就越高
  4. 假设每一个被划分的块都有对应层级的字母标识,那么最终就可以通过趋近于无限的划分,将整个地图,用无数个像素点描绘出来
  5. 同理,任何一个位置,都可以用足够长的字符串标识出来
  6. 这就是geohash

    Geohash经度对照表

    image.png
    可以看出,当geohash长度为9时,可以将经度细化到5米左右,也就是每个像素块的面积为5m*5m

    5.聚合点

    经过了geohash的学习,接下来就可以了解es中提供的地理位置聚合了。es中共提供了以下几种聚合方法

  7. geo_distance(地理位置距离):将文档按照距离围绕一个中心点来分组聚合

  8. geohash_grid(网格聚合):将文档按照 geohash 范围来分组聚合,用来显示在地图上
  9. geo_bounds(地理位置边界):返回一个包含所有坐标点的边界的矩形左上右下经纬度坐标,这对显示地图时缩放比例的选择非常有用。

接下来逐个讲解

geo_distance(地理位置距离)

给定圆心和聚合范围集合,可以统计出距离圆心递进距离区间内的点的数量。当然可以结合递归聚合做任何事情

命令格式

  1. GET omission/_search
  2. {
  3. "aggs": {
  4. "geo_distance_example": {
  5. "geo_distance": {
  6. "field": "location",
  7. "origin": {
  8. "lat": 39.56,
  9. "lon": 116.20
  10. },
  11. "ranges": [
  12. {
  13. "from": 0,
  14. "to": 1000
  15. },
  16. {
  17. "from": 1000,
  18. "to": 2000
  19. }
  20. ],
  21. "unit": "km",
  22. "distance_type": "plane"
  23. }
  24. }
  25. }
  26. }
  1. field:聚合字段、
  2. origin:圆心点经纬度坐标
  3. ranges:统计范围,例如示例中,统计了0~1000km范围、1000km到2000km范围
  4. unit:范围单位
  5. distance_type:距离计算方式,包括arc和plane两种

    示例

    统计距离北京(包括北京)0~1000km范围、1000km到2000km范围内的省市 ```json GET omission/_search { “aggs”: { “geo_distance_example”: { “geo_distance”: {
    1. "field": "location",
    2. "origin": {
    3. "lat": 39.56,
    4. "lon": 116.20
    5. },
    6. "ranges": [
    7. {
    8. "from": 0,
    9. "to": 1000
    10. },
    11. {
    12. "from": 1000,
    13. "to": 2000
    14. }
    15. ],
    16. "unit": "km",
    17. "distance_type": "plane"
    } } } }
  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/28218714/1660728296544-29a6baf3-bf5b-4cc1-bcc9-f79e0a157f78.png#clientId=u42b9ee89-1f79-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=689&id=uc5666a40&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1033&originWidth=1584&originalType=binary&ratio=1&rotation=0&showTitle=false&size=173247&status=done&style=none&taskId=u1710bff0-f0db-405d-b7e1-75df1ea0269&title=&width=1056)<br />如图,0~1000km范围内有两个城市:北京,山东。1000~2000km内有两个城市:湖北,湖南
  2. <a name="dHP1p"></a>
  3. ### geohash_grid(网格聚合)
  4. 通过geohash,将相同像素块内的坐标点聚合。聚合结果的key通过geohash来表示
  5. <a name="Po7hE"></a>
  6. #### 命令格式
  7. ```json
  8. GET omission/_search
  9. {
  10. "aggs": {
  11. "geohash_grid_example":{
  12. "geohash_grid": {
  13. "field": "location",
  14. "precision": 1
  15. }
  16. }
  17. }
  18. }
  1. field:聚合字段
  2. precision:geohash字符串长度,长度越长,精度越高

    示例

    网格聚合,指定geohash长度为1

    1. GET omission/_search
    2. {
    3. "aggs": {
    4. "geohash_grid_example":{
    5. "geohash_grid": {
    6. "field": "location",
    7. "precision": 1
    8. }
    9. }
    10. }
    11. }

    image.png
    可以看到,聚合结果为2个像素块,w包含5个点,t包含1个点
    此时我们扩大精确度为4
    image.png
    可以看到因为精度提高,每个像素块的面积变小,因此结果更为精细,聚合结果为6个像素块。

    geo_bounds(地理位置边界)

    有时候,我们需要一个范围,包括所有存储的点,而且这个范围越小越好,越小经度越高。
    es中提供了geo_bounds来计算出一个矩形地理位置边界,聚合结果会返回矩形的左上和右下坐标

    命令格式

    1. GET omission/_search
    2. {
    3. "aggs": {
    4. "geo_bound_example":{
    5. "geo_bounds": {
    6. "field": "location"
    7. }
    8. }
    9. }
    10. }
  3. field:聚合字段

    示例

    得到一个可以包含所有已存储数据的矩形

    1. GET omission/_search
    2. {
    3. "aggs": {
    4. "geo_bound_example":{
    5. "geo_bounds": {
    6. "field": "location"
    7. }
    8. }
    9. }
    10. }

    image.png
    如图,返回了一个矩形左上和右下的坐标

    6.索引图形

    es中使用geo_shape来存储一个地理位置图形,在有些场景下,我们可以利用这个功能,计算路线的交叉点,图形中包含了哪些点等信息
    geo-shape 不能用于计算距离、排序、打分以及聚合。

    建立索引

    建立索引时指定字段类型为geo_shape即可,如下示例:

    1. PUT shape_index
    2. {
    3. "mappings": {
    4. "properties": {
    5. "name":{
    6. "type": "text",
    7. "analyzer": "ik_max_word"
    8. },
    9. "location":{
    10. "type": "geo_shape"
    11. }
    12. }
    13. }
    14. }

    存储数据

    geo_shape数据类型支持的数据结构为geoJson,其中geo_json的基础数据类型为

    1. {
    2. "type":"Point",
    3. "coordinates":[
    4. 100,
    5. 0
    6. ]
    7. }
  4. type:geojson类型 | Elasticsearch 类型 | 说明 | | —- | —- | | point | 一个单独的经纬度坐标点 | | linestring | 任意的线条,由两到多个点组成 | | polygon | 由 N+1 个点组成的封闭 N 边形 | | multipoint | 一组不连续但有可能相关联的点 | | multilinestring | 多条不关联的线 | | multipolygon | 多个不关联的多边形 | | geometrycollection | 几何对象的集合 | | envelop | 由左上角坐标或右下角坐标确定的封闭矩形 | | circle | 由圆心和半径确定的圆,默认单位为米 |

  5. coordinates:坐标,不同类型对应的坐标组合也不同

参考下图录入数据
image.png
录入北京坐标点信息

  1. PUT /shape_index/_doc/bei_jing_point
  2. {
  3. "name" : "北京",
  4. "location" : {
  5. "type" : "point",
  6. "coordinates" : [116.20,39.56]
  7. }
  8. }

录入第一个三角形信息,包括三个点,需要注意的是,多边形必须闭合

  1. 甘肃:92.13,32.31
  2. 黑龙江:125.03,50.49
  3. 台湾:119.18,20.45

    1. PUT /shape_index/_doc/ght_triangle
    2. {
    3. "name": "甘肃黑龙江台湾三角形",
    4. "location": {
    5. "type": "polygon",
    6. "coordinates": [
    7. [
    8. [
    9. 92.13,
    10. 32.31
    11. ],
    12. [
    13. 125.03,
    14. 50.49
    15. ],
    16. [
    17. 119.18,
    18. 20.45
    19. ],
    20. [
    21. 92.13,
    22. 32.31
    23. ]
    24. ]
    25. ]
    26. }
    27. }

    录入第二个三角形信息,包括三个点,需要注意的是,多边形必须闭合

  4. 宁夏:105.49,38.08

  5. 新疆:96.37,42.45
  6. 西藏:80.24,31.29

    1. PUT /shape_index/_doc/nxx_triangle
    2. {
    3. "name": "宁夏新疆西藏三角形",
    4. "location": {
    5. "type": "polygon",
    6. "coordinates": [
    7. [
    8. [
    9. 105.49,
    10. 38.08
    11. ],
    12. [
    13. 96.37,
    14. 42.45
    15. ],
    16. [
    17. 80.24,
    18. 31.29
    19. ],
    20. [
    21. 105.49,
    22. 38.08
    23. ]
    24. ]
    25. ]
    26. }
    27. }

    7.查询形状

    不同形状查询

    es中通过geo_shape命令来查询地理位置图形,可以用来查询重叠图形,完全不重叠图形,完全包含图形

    命令格式

    1. GET shape_index/_search
    2. {
    3. "query": {
    4. "geo_shape": {
    5. "location": {
    6. "shape": {
    7. "type": "polygon",
    8. "coordinates": [
    9. [
    10. [
    11. 105.49,
    12. 38.08
    13. ],
    14. [
    15. 96.37,
    16. 42.45
    17. ],
    18. [
    19. 80.24,
    20. 31.29
    21. ],
    22. [
    23. 105.49,
    24. 38.08
    25. ]
    26. ]
    27. ]
    28. },
    29. "relation": "disjoint"
    30. }
    31. }
    32. }
    33. }
  7. geo_shape:枚举类型固定

  8. location:查询字段名称
  9. shape:枚举类型固定,里面的图形符合geojson即可
  10. relation:图形关系,分为以下三种 :::success

  11. intersects:(默认)查询的形状与索引的形状有重叠。

  12. disjoint:查询的形状与索引的形状完全不重叠。
  13. within:索引的形状完全被包含在查询的形状中。不支持直线几何图形。 :::

    示例

  14. 查询甘肃黑龙江台湾三角形完全包含的,理论上返回北京点

    1. GET shape_index/_search
    2. {
    3. "query": {
    4. "geo_shape": {
    5. "location": {
    6. "shape": {
    7. "type": "polygon",
    8. "coordinates": [
    9. [
    10. [
    11. 92.13,
    12. 32.31
    13. ],
    14. [
    15. 125.03,
    16. 50.49
    17. ],
    18. [
    19. 119.18,
    20. 20.45
    21. ],
    22. [
    23. 92.13,
    24. 32.31
    25. ]
    26. ]
    27. ]
    28. },
    29. "relation": "within"
    30. }
    31. }
    32. }
    33. }

    image.png
    如图,完全包含北京,与预期结果一致

  15. 查询甘肃黑龙江台湾三角形有重叠的,理论上返回北京点,甘肃黑龙江台湾三角形,宁夏新疆西藏三角形

    1. GET shape_index/_search
    2. {
    3. "query": {
    4. "geo_shape": {
    5. "location": {
    6. "shape": {
    7. "type": "polygon",
    8. "coordinates": [
    9. [
    10. [
    11. 92.13,
    12. 32.31
    13. ],
    14. [
    15. 125.03,
    16. 50.49
    17. ],
    18. [
    19. 119.18,
    20. 20.45
    21. ],
    22. [
    23. 92.13,
    24. 32.31
    25. ]
    26. ]
    27. ]
    28. },
    29. "relation": "intersects"
    30. }
    31. }
    32. }
    33. }

    image.png
    如图,全部返回,与预期结果一致

  16. 查询宁夏新疆西藏三角形完全不包含的,理论上返回北京点

    1. GET shape_index/_search
    2. {
    3. "query": {
    4. "geo_shape": {
    5. "location": {
    6. "shape": {
    7. "type" : "polygon",
    8. "coordinates" : [
    9. [
    10. [
    11. 105.49,
    12. 38.08
    13. ],
    14. [
    15. 96.37,
    16. 42.45
    17. ],
    18. [
    19. 80.24,
    20. 31.29
    21. ],
    22. [
    23. 105.49,
    24. 38.08
    25. ]
    26. ]
    27. ]
    28. },
    29. "relation": "disjoint"
    30. }
    31. }
    32. }
    33. }

    image.png
    如图,返回北京点,与预期结果一致

    使用已经存储的图形

    同样可以使用已经存储好的图形,进行计算

    命令格式

    1. GET shape_index/_search
    2. {
    3. "query": {
    4. "geo_shape": {
    5. "location": {
    6. "relation": "within",
    7. "indexed_shape": {
    8. "index": "shape_index",
    9. "id": "ght_triangle",
    10. "path": "location"
    11. }
    12. }
    13. }
    14. }
    15. }
  17. location:查询字段

  18. relation:图形关系
  19. indexed_shape:枚举类型固定字段
  20. index:索引
  21. id:文档ID
  22. path:文档字段

    示例

    查询甘肃黑龙江台湾三角形完全包含的点,理论上返回北京点
    1. GET shape_index/_search
    2. {
    3. "query": {
    4. "geo_shape": {
    5. "location": {
    6. "relation": "within",
    7. "indexed_shape": {
    8. "index": "shape_index",
    9. "id": "ght_triangle",
    10. "path": "location"
    11. }
    12. }
    13. }
    14. }
    15. }
    image.png
    如图,返回结果与预期结果一致