Geopoint 字段类型编辑

类型为 geo_point 的字段接受经纬度对,可用于

geo_shapepoint 一样,geo_point 可以用 GeoJSONWell-Known Text 格式指定。但是,出于方便和历史原因,还支持许多其他格式。总共有六种方法可以指定地理点,如下所示

response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        location: {
          type: 'geo_point'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    text: 'Geopoint as an object using GeoJSON format',
    location: {
      type: 'Point',
      coordinates: [
        -71.34,
        41.12
      ]
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 2,
  body: {
    text: 'Geopoint as a WKT POINT primitive',
    location: 'POINT (-71.34 41.12)'
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 3,
  body: {
    text: "Geopoint as an object with 'lat' and 'lon' keys",
    location: {
      lat: 41.12,
      lon: -71.34
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 4,
  body: {
    text: 'Geopoint as an array',
    location: [
      -71.34,
      41.12
    ]
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 5,
  body: {
    text: 'Geopoint as a string',
    location: '41.12,-71.34'
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 6,
  body: {
    text: 'Geopoint as a geohash',
    location: 'drm3btev3e86'
  }
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      geo_bounding_box: {
        location: {
          top_left: {
            lat: 42,
            lon: -72
          },
          bottom_right: {
            lat: 40,
            lon: -74
          }
        }
      }
    }
  }
)
puts response
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "text": "Geopoint as an object using GeoJSON format",
  "location": { 
    "type": "Point",
    "coordinates": [-71.34, 41.12]
  }
}

PUT my-index-000001/_doc/2
{
  "text": "Geopoint as a WKT POINT primitive",
  "location" : "POINT (-71.34 41.12)" 
}

PUT my-index-000001/_doc/3
{
  "text": "Geopoint as an object with 'lat' and 'lon' keys",
  "location": { 
    "lat": 41.12,
    "lon": -71.34
  }
}

PUT my-index-000001/_doc/4
{
  "text": "Geopoint as an array",
  "location": [ -71.34, 41.12 ] 
}

PUT my-index-000001/_doc/5
{
  "text": "Geopoint as a string",
  "location": "41.12,-71.34" 
}

PUT my-index-000001/_doc/6
{
  "text": "Geopoint as a geohash",
  "location": "drm3btev3e86" 
}

GET my-index-000001/_search
{
  "query": {
    "geo_bounding_box": { 
      "location": {
        "top_left": {
          "lat": 42,
          "lon": -72
        },
        "bottom_right": {
          "lat": 40,
          "lon": -74
        }
      }
    }
  }
}

以对象形式表示的地理点,采用 GeoJSON 格式,具有 typecoordinates 键。

Well-Known Text POINT 形式表示的地理点,格式为:"POINT(lon lat)"

以对象形式表示的地理点,具有 latlon 键。

以数组形式表示的地理点,格式为:[ lon, lat]

以字符串形式表示的地理点,格式为:"lat,lon"

以 geohash 形式表示的地理点。

查找落在框内的所有地理点的地理边界框查询。

以数组或字符串形式表示的地理点

请注意,字符串地理点的顺序为 lat,lon,而数组地理点、GeoJSON 和 WKT 的顺序则相反:lon,lat

造成这种情况的原因是历史原因。地理学家传统上将 纬度 放在 经度 之前,而最近为地理数据指定的格式(如 GeoJSONWell-Known Text)将 经度 放在 纬度 之前(东经放在北纬之前),以匹配将 x 放在 y 之前的数学约定。

点可以表示为 geohash。Geohash 是 base32 编码的字符串,包含纬度和经度的交织位。geohash 中的每个字符都会为精度增加 5 位。因此,hash 越长,精度越高。出于索引目的,geohash 会转换为经纬度对。在此过程中,只使用前 12 个字符,因此在 geohash 中指定超过 12 个字符不会提高精度。12 个字符提供 60 位,这应该可以将可能的误差降低到 2 厘米以下。

geo_point 字段的参数编辑

geo_point 字段接受以下参数

ignore_malformed

如果为 true,则忽略格式错误的地理点。如果为 false(默认值),则格式错误的地理点会引发异常并拒绝整个文档。如果地理点的纬度超出范围 -90 ⇐ 纬度 ⇐ 90,或经度超出范围 -180 ⇐ 经度 ⇐ 180,则该地理点被视为格式错误。请注意,如果使用了 script 参数,则无法设置此参数。

ignore_z_value

如果为 true(默认值),则会接受三维点(存储在源中),但只会索引纬度和经度值;第三维将被忽略。如果为 false,则包含纬度和经度(二维)值以外的任何值的地理点会引发异常并拒绝整个文档。请注意,如果使用了 script 参数,则无法设置此参数。

index

该字段是否应快速可搜索?接受 true(默认值)和 false。仅启用了 doc_values 的字段仍然可以查询,但速度较慢。

null_value

接受一个地理点值,该值将替换任何显式 null 值。默认为 null,这意味着该字段将被视为缺失。请注意,如果使用了 script 参数,则无法设置此参数。

on_script_error

定义如果由 script 参数定义的脚本在索引时引发错误,该怎么办。接受 fail(默认值),这会导致整个文档被拒绝,以及 continue,这会将该字段注册到文档的 _ignored 元数据字段中并继续索引。此参数只能在也设置了 script 字段的情况下设置。

script

如果设置了此参数,则该字段将索引由该脚本生成的的值,而不是直接从源读取值。如果在输入文档中为该字段设置了值,则该文档将被拒绝并出现错误。脚本的格式与其 运行时等效项 相同,并且应将点作为 (lat, lon) 双精度值对发出。

在脚本中使用地理点编辑

在脚本中访问地理点的值时,该值将作为 GeoPoint 对象返回,这允许分别访问 .lat.lon

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

出于性能原因,最好直接访问纬度/经度值

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

合成源编辑

合成 _source 仅对 TSDB 索引(将 index.mode 设置为 time_series 的索引)普遍可用。对于其他索引,合成 _source 处于技术预览阶段。技术预览中的功能可能会在将来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览中的功能不受官方 GA 功能的支持 SLA 的约束。

geo_point 字段在其默认配置中支持 合成 _source。合成 _source 不能与 ignore_malformedcopy_to 或禁用 doc_values 一起使用。

合成源始终对 geo_point 字段进行排序(首先按纬度,然后按经度),并将它们缩减为其存储的精度。例如

response = client.indices.create(
  index: 'idx',
  body: {
    mappings: {
      _source: {
        mode: 'synthetic'
      },
      properties: {
        point: {
          type: 'geo_point'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'idx',
  id: 1,
  body: {
    point: [
      {
        lat: -90,
        lon: -80
      },
      {
        lat: 10,
        lon: 30
      }
    ]
  }
)
puts response
PUT idx
{
  "mappings": {
    "_source": { "mode": "synthetic" },
    "properties": {
      "point": { "type": "geo_point" }
    }
  }
}
PUT idx/_doc/1
{
  "point": [
    {"lat":-90, "lon":-80},
    {"lat":10, "lon":30}
  ]
}

将变为

{
  "point": [
    {"lat":-90.0, "lon":-80.00000000931323},
    {"lat":9.999999990686774, "lon":29.999999972060323}
   ]
}