原英文版地址: https://www.elastic.co/guide/en/elasticsearch/reference/7.7/geo-shape.html, 原文档版权归 www.elastic.co 所有
本地英文版地址: ../en/geo-shape.html

geo_shape(地理形状)数据类型

geo_shape数据类型便于索引和搜索任意地理形状,如矩形和多边形。 当被索引的数据或被执行的查询包含形状而不仅仅是坐标点时,应该使用它。

可以使用geo_shape查询来查询使用此类型的文档。

映射之选项

geo_shape 映射将 geo_json 几何对象映射到 geo_shape 类型。 要启用它,用户必须显式地将字段映射为 geo_shape 类型。

选项 描述 默认值

tree

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 要使用的PrefixTree实现的名称:实现 GeohashPrefixTree 的是geohash,实现 QuadPrefixTree 的是quadtree。 注意:此参数仅与term(词项) 和 recursive(递归) 策略相关。

quadtree

precision

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 可以使用此参数代替tree_levels来为tree_levels参数设置适当的值。 该值指定了所需的精度,Elasticsearch 将计算最佳的 tree_levels 值来满足该精度。 该值应当是后面跟可选距离单位的数字。 有效的距离单位包括:ininch, ydyardmimileskmkilometersmmeterscmcentimetersmmmillimeters。 注意:此参数仅与term(词项) 和 recursive(递归) 策略相关。

50m

tree_levels

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 PrefixTree 可以使用的最大层数。 这可以用来控制形状表示的精度,从而控制索引的词项的数量。 默认为所选的 PrefixTree 实现的默认值。 由于此参数需要对底层实现有一定程度的了解,因此用户可以使用precision参数代替之。 然而,Elasticsearch只在内部使用 tree_levels 参数,即使你使用了参数precision,这也是通过映射API返回的。 注意:此参数仅与term(词项) 和 recursive(递归) 策略相关。

various

strategy

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 参数strategy定义了在编制索引和搜索时如何表示形状的方法。 它还会影响可用的功能,因此建议让 Elasticsearch 自动设置该参数。 有两种可用的参数:recursiveterm。 recursive 和 term 策略已废弃,在未来的版本中将会删除。 虽然它们仍然可用,但 term 策略仅支持 point(坐标点) 类型(参数points_only将自动设置为 true),而 recursive 策略支持所有 shape(形状) 类型。 (重要提示:有关这些策略的更多详细信息,请参考前缀树)

recursive

distance_error_pct

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 用作 PrefixTree 的暗示,告诉它应该有多精确。 默认值为 0.025 (2.5%),支持的最大值为 0.5。 性能说明:如果明确申明了precisiontree_level定义,该值将默认为 0。 这保证了映射中定义的空间精度。 这可能导致低误差的高分辨率形状占用大量内存(例如,1m 精度的大形状误差小于 0.001)。 为了提高索引性能(以牺牲查询精度为代价),显式地定义tree_levelprecision,并使用合理的distance_error_pct,注意大的形状会有更大的误报。 注意:此参数仅与term(词项) 和 recursive(递归) 策略相关。

0.025

orientation

选择性地定义如何解释多边形/多重多边形的顶点顺序。 该参数定义了两个坐标系规则(右手 right-hand 或左手 left-hand)中的一个,每一个都可以用三种不同的方式指定。 1. 右手(right-hand) 规则:rightccwcounterclockwise(逆时针); 2. 左手(left-hand)规则:leftcwclockwise(顺时针)。 默认方向(counterclockwise,逆时针)符合 OGC 标准,该标准以逆时针顺序定义外环顶点,以顺时针顺序定义内环顶点(孔)。 在 geo_shape 映射中设置此参数会为 geo_shape 字段的坐标列表显式设置折点顺序,但可以被每个单独的 GeoJSON 或 WKT 文档所覆盖。

ccw

points_only

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 将此选项设置为true(默认为false)将仅为 点(point) 形状配置 geo_shape 字段类型(注意:尚不支持多点)。 当已知只有点将被索引时,这优化了 geohashquadtree 的索引编制和搜索性能。 目前,不能在geo_point类型的字段上执行 geo_shape 查询。 此选项通过提高geo_shape字段的点性能来弥补这一差距,从而使geo_shape查询在 "point only" 字段上达到最佳效果。

false

ignore_malformed

如果为 true,则忽略格式错误的 GeoJSON 或 WKT 形状。 如果为 false(默认值),格式错误的 GeoJSON 和 WKT 形状将导致异常并拒绝整个文档。

false

ignore_z_value

如果为true(默认),将接受三个维度点(存储在source中),但仅索引纬度(latitude)和经度(longitude)值;第三维度被忽略。 如果为false,包含任何超过纬度和经度(二维)值的地理坐标点将导致异常并拒绝整个文档。

true

coerce

如果为true,多边形中未闭合的线性环将自动闭合。

false

编制索引的方法

通过将形状分解成三角形网格并将每个三角形索引为 BKD 树中的 7 维点来索引 geo_shape 类型。 这提供了近乎完美的空间分辨率(低至1e-7十进制精度),因为所有空间关系都是使用原始形状的编码矢量表示来计算的,而不是前缀树(prefix trees)索引方法所使用的光栅网格表示。 镶嵌器的性能主要取决于定义多边形/多多边形的顶点数量。 虽然这是默认的索引技术,但是仍然可以通过根据适当的M映射选项设置treestrategy参数来使用前缀树。 请注意,这些参数现在已被废弃,并将在未来版本中删除。

重要提示

CONTAINS(包含) 关系查询 - 当使用新的默认向量索引策略时,使用7.5.0或更高版本的 ElasticSearch 创建的索引支持把relation定义为containsgeo_shape查询。

前缀树(prefix trees)

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 为了在倒排索引中有效地表示形状,使用 PrefixTree (前缀树)的实现将形状转换为一系列表示网格正方形(通常称为 rasters, 即“栅格”)的哈希。 树的概念来自于 PrefixTree 使用多个网格层的事实,每个网格层都以越来越高的精度来表示 Earth(地球)。 这可以被认为是在更高的缩放级别下增加地图或图像的细节级别。 由于这种方法会导致索引的形状的精度问题,因此它已被弃用,取而代之的是将形状索引为三角形网格的矢量索引方法(参考索引方法)。

提供了多个 PrefixTree 实现方法:

  • GeohashPrefixTree:将geohash(地理哈希)用于网格正方形。 geohash 是经纬度交织的 base32 编码的字符串。 添加到 geohash 的每个字符代表另一个树级别,并为 geohash 增加 5 比特位的精度。 geohash 表示一个矩形区域,有32个子矩形。 Elasticsearch中的最大级数为 24;默认值为 9。
  • QuadPrefixTree:将quadtree(四叉树)用于网格正方形。 与 geohash 类似,quadtree(四叉树)交织纬度和经度的比特位,产生的哈希是一个比特位集。 四叉树中的树级别表示该比特位集中的 2 位,每个坐标一位。 Elasticsearch中四叉树的最大层数是 29;默认值为 21。
空间策略

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 所选择的索引实现方法依赖于选择如何分解形状(作为网格正方形或镶嵌的三角形网格)的空间策略。 每个策略回答以下问题:

  • 什么类型的形状可以被索引?
  • 可以使用哪些类型的查询操作和形状?
  • 它是否支持每个字段有多个形状?

提供了以下策略实现方法(具有相应的功能):

策略 支持的形状 支持的查询 多形状

recursive

所有

INTERSECTSDISJOINTWITHINCONTAINS

term

INTERSECTS

精确度

recursiveterm策略不能提供100%的准确性,并且根据它们的配置方式,它可能会为INTERSECTSWITHINCONTAINS查询返回一些假阳性,为DISJOINT查询返回一些假阴性。 为了减轻这种情况,为参数 tree_levels 选择一个合适的值并相应地调整期望值是很重要的。 例如,某个点可能靠近特定网格单元的边界,因此可能与仅匹配其旁边单元的查询不匹配,即使形状非常接近该点。

示例
PUT /index_name
{
    "mappings": {
        "properties": {
            "location": {
                "type": "geo_shape"
            }
        }
    }
}

这个映射定义使用默认的矢量实现将 location 字段映射为 geo_shape 类型。 它提供大约 1e-7十进制的精度。

前缀树(prefix tree)的性能考量

[6.6] 在6.6版本中废弃。不再使用 前缀树(PrefixTree)。 使用前缀树,Elasticsearch 在倒排索引和查询中使用树中的路径作为词项。 级别越高(精度也越高),生成的词项就越多。 当然,计算这些词项,将它们保存在内存中,以及将它们存储在磁盘上都是有代价的。 尤其是在树级别较高的情况下,即使数据量不多,索引也会变得非常大。 此外,特征的大小也很重要。 大而复杂的多边形会在较高的树级别上占用大量空间。 哪个设置是正确的取决于用例。 通常,人们会在准确性与索引大小和查询性能之间进行权衡。

对于这两种实现,Elasticsearch中的默认值是索引大小和赤道上50米的合理精度之间的折衷。 允许对数千万个形状进行索引,而不会使结果索引相对于输入大小过于膨胀。

如果search.allow_expensive_queries设置为 false,则不会对使用前缀树实现的地理形状执行 geo-shape 查询。

输入结构

可以使用GeoJSON众所周知的文本 (WKT) 格式来表示形状。 下表提供了 GeoJSON 和 WKT 与 Elasticsearch 类型的映射:

GeoJSON 类型 WKT 类型 Elasticsearch 类型 描述

Point

POINT

point

一个地理坐标。注意:Elasticsearch 仅使用 WGS-84 坐标。

LineString

LINESTRING

linestring

给定两点或多点的任意直线。

Polygon

POLYGON

polygon

一个闭合的多边形,其第一个点和最后一个点必须匹配,因此需要n + 1个顶点来创建一个n边形和至少4个顶点。

MultiPoint

MULTIPOINT

multipoint

一组未连接但可能相关的点。

MultiLineString

MULTILINESTRING

multilinestring

一组独立的直线。

MultiPolygon

MULTIPOLYGON

multipolygon

一组独立的多边形。

GeometryCollection

GEOMETRYCOLLECTION

geometrycollection

类似于multi*形状的 GeoJSON 形状,只是多种类型可以共存(例如,Point 和 LineString)。

N/A

BBOX

envelope

通过仅指定左上角和右下角的点来指定的边界矩形或封套。

N/A

N/A

circle

由圆心和半径指定的圆,其单位默认为METERS

对于所有类型,内部typecoordinates(坐标)字段都是必需的。

在 GeoJSON 和 WKT 以及 Elasticsearch 中,坐标数组中正确的坐标顺序是经度(longitude)、纬度(latitude) (X,Y)。 这不同于许多地理空间API(例如Google Maps),它们通常使用通俗的纬度、经度(Y,X)。

Point

一个 point (点) 是一个地理坐标,比如一栋建筑的位置或者智能手机的 Geolocation API 给出的当前位置。 下面是 GeoJSON 中一个 point 的例子:

POST /example/_doc
{
    "location" : {
        "type" : "point",
        "coordinates" : [-77.03653, 38.897676]
    }
}

下面是 WKT 中一个 point 的例子:

POST /example/_doc
{
    "location" : "POINT (-77.03653 38.897676)"
}
LineString

由两个或多个位置的数组定义的linestring。 通过仅指定两个点,linestring将表示一条直线。 指定两个以上的点会创建任意路径。 下面是 GeoJSON 中一个 LineString 的例子:

POST /example/_doc
{
    "location" : {
        "type" : "linestring",
        "coordinates" : [[-77.03653, 38.897676], [-77.009051, 38.889939]]
    }
}

下面是 WKT 中一个 LineString 的例子:

POST /example/_doc
{
    "location" : "LINESTRING (-77.03653 38.897676, -77.009051 38.889939)"
}

上面的linestring将画一条从白宫到美国国会大厦的直线。

Polygon

多边形是由一系列点定义的。 每个(外部)列表中的第一个和最后一个点必须相同(多边形必须是闭合的)。 下面是 GeoJSON 中一个 Polygon 的例子:

POST /example/_doc
{
    "location" : {
        "type" : "polygon",
        "coordinates" : [
            [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
        ]
    }
}

下面是 WKT 中一个 Polygon 的例子:

POST /example/_doc
{
    "location" : "POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0))"
}

第一个数组表示多边形的外部边界,其他数组表示内部形状(“孔”)。 下面是 GeoJSON 中一个有孔的 Polygon 的例子:

POST /example/_doc
{
    "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] ]
        ]
    }
}

下面是 WKT 中一个有孔的 Polygon 的例子:

POST /example/_doc
{
    "location" : "POLYGON ((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))"
}

重要提示:WKT 没有强制顶点的特定顺序,因此日期变更线和极点周围的多边形可能不明确。 GeoJSON要求外部多边形必须为逆时针方向,内部形状必须为顺时针方向,这符合开放地理空间联盟(Open Geospatial Consortium,OGC)关于顶点排序的简单特性访问规范。

如果顺时针和逆时针多边形看起来没有穿过日期变更线(即,它们穿过的经度小于180°),则 Elasticsearch 接受这两种多边形,但对于穿过日期变更线的多边形(或宽度大于180°的其他多边形), Elasticsearch 要求顶点排序符合 OGC 和 GeoJSON 规范。 否则,可能会创建非预期的多边形,并会返回意外的查询/过滤结果。

下面提供了一个不明确多边形的示例。 Elasticsearch 将应用 GeoJSON 标准来消除导致与日期变更线相交的多边形的模糊性。

POST /example/_doc
{
    "location" : {
        "type" : "polygon",
        "coordinates" : [
            [ [-177.0, 10.0], [176.0, 15.0], [172.0, 0.0], [176.0, -15.0], [-177.0, -10.0], [-177.0, 10.0] ],
            [ [178.2, 8.2], [-178.8, 8.2], [-180.8, -8.8], [178.2, 8.8] ]
        ]
    }
}

设置 geo_shape 映射时,可以定义一个参数orientation(请参见映射选项)。 这将为映射的 geo_shape 字段上的坐标列表定义顶点顺序。 它也可以在每个文档上被覆盖。 以下是一个覆盖文档上的方向的示例:

POST /example/_doc
{
    "location" : {
        "type" : "polygon",
        "orientation" : "clockwise",
        "coordinates" : [
            [ [100.0, 0.0], [100.0, 1.0], [101.0, 1.0], [101.0, 0.0], [100.0, 0.0] ]
        ]
    }
}
MultiPoint

下面是一个 GeoJSON 格式 point 列表的示例:

POST /example/_doc
{
    "location" : {
        "type" : "multipoint",
        "coordinates" : [
            [102.0, 2.0], [103.0, 2.0]
        ]
    }
}

下面是一个 WKT 格式 point 列表的示例:

POST /example/_doc
{
    "location" : "MULTIPOINT (102.0 2.0, 103.0 2.0)"
}
MultiLineString

下面是一个 GeoJSON 格式 linestring 列表的示例:

POST /example/_doc
{
    "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] ]
        ]
    }
}

下面是一个 WKT 格式 linestring 列表的示例:

POST /example/_doc
{
    "location" : "MULTILINESTRING ((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))"
}
MultiPolygon

下面是一个 GeoJSON 格式 polygon 列表的示例(第二个多边形包含一个孔):

POST /example/_doc
{
    "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]] ]
        ]
    }
}

下面是一个 WKT 格式 polygon 列表的示例(第二个多边形包含一个孔):

POST /example/_doc
{
    "location" : "MULTIPOLYGON (((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)))"
}
Geometry Collection

下面是一个 GeoJSON 格式 几何对象集合的示例:

POST /example/_doc
{
    "location" : {
        "type": "geometrycollection",
        "geometries": [
            {
                "type": "point",
                "coordinates": [100.0, 0.0]
            },
            {
                "type": "linestring",
                "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
            }
        ]
    }
}

下面是一个 WKT 格式 几何对象集合的示例:

POST /example/_doc
{
    "location" : "GEOMETRYCOLLECTION (POINT (100.0 0.0), LINESTRING (101.0 0.0, 102.0 1.0))"
}
envelope (边界矩形)

Elasticsearch 支持一种envelope类型,它由形状的左上角和右下角的坐标组成,以[[minLon, maxLat], [maxLon, minLat]]格式表示一个边界矩形:

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

以下是使用 WKT BBOX 格式的 envelope 的示例:

注意: WKT规范要求以下顺序:minLon,maxLon,maxLat,minLat。

POST /example/_doc
{
    "location" : "BBOX (100.0, 102.0, 2.0, 0.0)"
}
circle (圆形)

Elasticsearch 支持一种circle类型,由一个中心点和一个半径组成。 注意,只有在 前缀树(prefix tree) 使用recursive策略时,才能对这个圆的表示进行索引。 对于默认的索引方法,circle 应该使用POLYGON来近似表示。

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

注意:内 radius(半径) 字段是必需的。 如果半径的数值后面没有指定单位,那么半径的单位将默认为METERS

注意:GeoJSON和WKT都不支持点半径圆类型。 注意: GeoJSON 和 WKT 都不支持 point-radius circle 类型。

排序和检索索引形状

由于形状的复杂的输入结构和索引表示,目前无法对形状进行排序或直接检索它们的字段。 geo_shape 值只能通过_source字段检索。