# 3.2.1.3.Geo地理数据类型

|        分类       | 数据类型                      |
| :-------------: | ------------------------- |
| Geo-point 地理坐标型 | geo\_point数据类型：描述纬度/经度坐标  |
| Geo-Shape 地理图形型 | geo\_shape数据类型：描述多边形等复杂形状 |

## Geo-point 地理坐标型

geo-points类型字段使用横纵坐标经伟度，使用方法

* 1.在边界框内或多边形内，找中心点和离中心点的一定距离的点。
* 2.从地理位置或从中心点的距离组成搜索文本
* 3.根据位置距离给搜索文本评分
* 4.根据得分进行搜索文本排序

有四种方法可以指定地理点，如下所示

```
PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "location": {
          "type": "geo_point"
        }
      }
    }
  }
}

PUT my_index/my_type/1
{
  "text": "Geo-point as an object",
  "location": {        # 1
    "lat": 41.12,
    "lon": -71.34
  }
}

PUT my_index/my_type/2
{
  "text": "Geo-point as a string",
  "location": "41.12,-71.34"          # 2
}

PUT my_index/my_type/3
{
  "text": "Geo-point as a geohash",
  "location": "drm3btev3e86"          # 3
}

PUT my_index/my_type/4
{
  "text": "Geo-point as an array",
  "location": [ -71.34, 41.12 ]      # 4
}

GET my_index/_search
{
  "query": {
    "geo_bounding_box": {          # 5
      "location": {
        "top_left": {
          "lat": 42,
          "lon": -72
        },
        "bottom_right": {
          "lat": 40,
          "lon": -74
        }
      }
    }
  }
}
```

| 1 | Geo-point 可以用对象表示描述：有横坐标和纵坐标两点.        |
| - | -------------------------------------- |
| 2 | Geo-point 可以带有“，”间隔符的字符串表示描述.          |
| 3 | Geo-point 可以用geohash哈希来表示描述.           |
| 4 | Geo-point 可以用这样的数组格式: \[ lon, lat]来表示描 |
| 5 | 可以用查询边界框里面的点来表示描述.                     |

> 注意:表示为数组或字符串的地理点
>
> 请注意用string类型描述geo-points格式，和数组类型描述geo-points格式
>
> 正好，模纵坐标可以放string类型或数组类型，但是数组是可以转换成JOSN格式

### Geo\_point 字段参数

下面是Geo\_point 字段参数

| ignore\_malformed | 如果true,异常Geo\_point数据被忽略，false,将会抛出异常，不接受执行整个搜索文本（默认为false） |
| ----------------- | ----------------------------------------------------------- |

### 使用geo-points脚本

使用脚本查询一个地理点的数据时，该值作为一个GeoPoint对象返回，它允许访问。LAT和LON。值分别为：

```
def geopoint = doc['location'].value;
def lat      = geopoint.lat;
def lon      = geopoint.lon;
```

对于性能的原因，请直接访问搜索文本的经度值：

```
lat      = doc['location'].lat;
lon      = doc['location'].lon;
```

## Geo-Shape 地理图形型

Geo\_shape数据类型有利于有助于索引和搜索任意地理形状，如：矩形和多边形。我们这样使用它：数据索引或执行点状数据查询

你能使用geo\_shape 查询引擎，查询搜索文本。

### Mapping 选项

Geo\_shape mapping 绘制geo\_shape 类型的 geo\_json 几何对象

| **Option**           | **Description**                                                                                                                                                                                                             | **Default** |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| tree                 | 使用PrefixTree ：geohash类型的GeohashPrefixTree 或`quadtree` 类型的QuadPrefixTree                                                                                                                                                     | geohash     |
| precision            | 这个参数可以用来代替tree\_levels设置为适当的值tree\_levels参数。该值指定所需的精度，Elasticsearch将计算出最佳有价值的精度tree\_levels。值应该是一个数字，然后是可选的距离单位。有效距离的单位包括：英寸，寸码，米，公里，米，厘米，毫米                                                                                | meters      |
| tree\_levels         | 这一点被prefixTree应用最多。这可以用来控制形状表示的精度，因些需要索引很多个词，选择prefixtree默认值，由于此参数要求对底层实现有一定程度的理解，因此用户可以使用精度参数。然而，Elasticsearch只用tree\_levels参数，这是通过映射的API，即使你使用精度的参数返回。                                                                    | 50m         |
| strategy             | 策略参数定义了如何在索引和搜索时间中表示形状的方法。它也影响的能力提供建议让Elasticsearch自动设置这个参数。有两种策略可供选择：递归和术语。长期的战略支撑点类型（的points\_only参数将被自动设置为true），递归策略支持所有的形状类型。（重要：参见前缀树获取更详细的信息）                                                                         | recursive   |
| distance\_error\_pct | 作为一个暗示，PrefixTree如何精确的应。默认值为0.025（2.5%），最大支持值为0.5。性能备注：这个值将默认为0如果精度或tree\_level定义明确定义。这保证映射中定义的级别的空间精度。这会导致高分辨率的内存使用率低（例如，100米的大图形和0.001错误）。提高索引性能（在查询精度成本）明确随着合理的distance\_error\_pct tree\_level或精度，指出大的形状将有更大的误报。        | 0.025       |
| orientation          | 可以定义如何解释/ multipolygons多边形顶点顺序。这个参数定义了两个坐标系统规则（右手或左手）中的一个，每个规则可以用三种不同的方式指定。1。右手定则：右，逆时针逆时针，2。左手定则：左，顺时针，顺时针。默认方向（逆时针）符合定义的顶点按逆时针顺序与外环内环OGC标准（S）的顶点（孔）按顺时针方向的。在geo\_shape映射这个参数设置显式设置为一个geo\_shape场坐标列表顶点顺序但可在每个GeoJSON文件重写。 | ccw         |
| points\_only         | 设置此选项为true（默认为false）配置点的geo\_shape字段类型形状（注：多点尚未支持）。这优化为Geohash和四叉树索引和搜索性能的时候它是已知的唯一的点会被索引。目前geo\_shape查询无法执行的geo\_point字段类型。这个选项，架起了一座桥梁，通过提高在geo\_shape场点的表现让geo\_shape查询优化一点场。                                            | false       |

### **Prefix trees(前缀树)**

有效的指数代表的形状，形状转换成一系列的哈希值代表方格（通常被称为“栅格”）使用一个prefixtree实现。树的概念来自这样一个事实：prefixtree采用多重网格层，每一个增加的精度水平代表地图。这可以看作是在更高的缩放级别上增加地图或图像的细节级别。

提供了多个prefixtree实现

* geohashprefixtree使用geohashes方格。geohashes是Base32编码字符串的纬度和经度的比特交织。所以哈希越长，它就越精确。每个字符添加到Geohash代表另一个树的水平和增加了5位精度的Geohash。一个Geohash表示一个矩形的面积，32个矩形。在Elasticsearch级别的最大量为24。
* quadprefixtree -使用一个四叉树的方格。类似Geohash，四叉树交错的经度和纬度产生的哈希位有点集。四叉树中的树级别代表这个位集中的2位，每个坐标的一位。在Elasticsearch的四叉树级别的最大量为50。&#x20;

#### **Spatial strategies**

prefixtree的实现依赖于一种分解提供的形状spatialstrategy（S）为近似方格。每种策略都回答以下问题：

1. 什么类型的形状可以被索引？
2. 可以使用什么类型的查询操作或形状？
3. 它支持每个字段超过一个形状吗？

提供了以下策略实现（具有相应的功能）：

| **Strategy** | **Supported Shapes**                                                                                  | **Supported Queries**                          | **Multiple Shapes** |
| ------------ | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ------------------- |
| `recursive`  | [All](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html#input-structure) | `INTERSECTS`, `DISJOINT`, `WITHIN`, `CONTAINS` | Yes                 |
| `term`       | [Points](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html#point)        | `INTERSECTS`                                   | Yes                 |

**Accuracy**

geo\_shape不提供100%的准确度，取决于它是如何配置它可能会返回一些假阳性或假阴性的某些查询。为了解决这个问题，这是选择的tree\_levels参数调整的预期因此适当的重要价值。例如，一个点可以在一个特定的网格单元的边界，因此可能不匹配的查询匹配的细胞在它旁边 - 虽然外形非常接近的点。

#### 例子：

```
PUT /example
{
    "mappings": {
        "doc": {
            "properties": {
                "location": {
                    "type": "geo_shape",
                    "tree": "quadtree",
                    "precision": "1m"
                }
            }
        }
    }
}
```

这个映射图位置字段中使用quad\_tree实现和精度1m geo\_shape型。Elasticsearch转化为tree\_levels设置26。

**关于系统性能方面的问题**

Elasticsearch使用路径的前缀树的索引和查询。级别越高（因而精度越高）生成的代码越多。当然，计算这些代码，将它们保存在内存中，并将它们存储在磁盘上都是有代价的。尤其是树级别较高的情况下，即使只有少量的数据，索引也可能变得非常大。此外，功能的大小也很重要。大而复杂的多边形可以在较高的树级别占用大量空间。哪个设置正确取决于用例。一般情况下，索引精度和查询性能都会降低准确性。

为实现在Elasticsearch默认索引的大小和在赤道精密50M的合理水平之间的一种折衷。这使得索引数以千万计的形状，而不会过度膨胀的结果指数太大，相对于输入大小。

### Input Structure

GeoJSON格式的是用来表示形状输入如下：

| **GeoJSON Type**   | **Elasticsearch Type** | **Description**                                                                                                        |
| ------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Point              | point                  | 单一地理坐标                                                                                                                 |
| LineString         | linestring             | 给定两个或多个点的任意线。                                                                                                          |
| Polygon            | polygon                | 一个封闭的多边形的第一个和最后一个点必须匹配，因此需要n + 1个顶点创建一个N边多边形和至少4个顶点。                                                                   |
| MultiPoint         | multipoint             | An array of unconnected, but likely related points.                                                                    |
| MultiLineString    | multilinestring        | An array of separate linestrings.                                                                                      |
| MultiPolygon       | multipolygon           | 一组单独的多边形。                                                                                                              |
| GeometryCollection | geometrycollection     | A GeoJSON shape similar to the multi\* shapes except that multiple types can coexist (e.g., a Point and a LineString). |
| N/A                | envelope               | A bounding rectangle, or envelope, specified by specifying only the top left and bottom right points.                  |
| N/A                | circle                 | A circle specified by a center point and radius with units, which default to METERS.                                   |

对于所有类型，都需要内部类型和坐标字段。

在GeoJSON，因此Elasticsearch，正确的坐标为经度、纬度（x，y）的坐标数组。这不同于许多地理空间API（例如，谷歌地图），它们通常使用纬度、经度（y、x）。

**Point**

一个点是一个单一的地理坐标位置，如建筑物或当前位置通过智能手机的地理定位API了。

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

**LineString**

由两个或两个以上的位置数组定义的线。通过指定两点的线表示一条直线。指定多于两个点会创建任意路径。

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

上面的线就画一直线，从白宫到美国的首都大厦。

**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] ]
        ]
    }
}
```

第一个数组代表多边形的外边界，其他数组表示内部形状（”holes”）

```
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] ]
        ]
    }
}
```

重要注意事项：

GeoJSON并不要求如此明确的多边形顶点在日界线内，顶点的特定顺序是可能的。为了减轻模糊开放地理空间联盟（OGC）的简单功能接入规范定义了下面的顶点顺序

* 外圈-逆时针方向
* 内圈-顺时针方向

多边形不越过日界线，顶点顺序将不在Elasticsearch。多边形做过日界线，Elasticsearch需要顶点顺序符合OGC规范。否则，可能会创建一个意外的多边形，并返回意外的查询/过滤结果。

下面提供了一个不明确多边形的示例。Elasticsearch将OGC标准消除产生一个多边形，越过日界线歧义。

```
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映射时（参见“映射optionsedit”）。这将定义的映射geo\_shape场坐标列表顶点顺序。它也可以覆盖在每个文档上。下面是覆盖文档方向的示例：

```
POST /example/doc
{
    "location" : {
        "type" : "polygon",
        "orientation" : "clockwise",
        "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] ]
        ]
    }
}
```

**MultiPoint**

GeoJSON点列表。

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

**MultiLineString**

GeoJSON线要素列表

```
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] ]
        ]
    }
}
```

**MultiPolygon**

GeoJSON多边形列表。

```
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]] ]
        ]
    }
}
```

**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] ]
            }
        ]
    }
}
```

**Envelope**

Elasticsearch支持一个信封式的，包括对形状代表一个矩形的左上角和右下角点的坐标：

```
POST /example/doc
{
    "location" : {
        "type" : "envelope",
        "coordinates" : [ [-45.0, 45.0], [45.0, -45.0] ]
    }
}
```

**Circle**

Elasticsearch支持圆式，它由一个中心点和半径：

```
POST /example/doc
{
    "location" : {
        "type" : "circle",
        "coordinates" : [-45.0, 45.0],
        "radius" : "100m"
    }
}
```

注：内半径(radius)字段是必需的。。如果未指定，则半径的单位将默认为米。

#### 排序和检索索引的形状(Sorting and Retrieving index Shapes) <a href="#geo-pointdatatype-sortingandretrievingindexshapes" id="geo-pointdatatype-sortingandretrievingindexshapes"></a>

由于复杂的输入结构和形状的索引表示，目前不可能对形状进行分类或直接检索它们的字段。geo\_shape值仅为检索通过`_source` field.
