geo_point 字段类型
geo_point 类型的字段接受经纬度对,可用于:
- 查找边界框内、距中心点一定距离内,或
geo_shape查询范围内的地理点(例如多边形内的点)。 - 按距中心点的距离聚合文档。
- 按地理网格聚合文档:
geo_hash、geo_tile或geo_hex。 - 使用指标聚合
geo_line将地理点聚合为轨迹。 - 将距离整合到文档的相关性评分中。
- 按距离对文档排序。
与 geo_shape 和 point 类型一样,geo_point 可以用 GeoJSON 和 Well-Known Text(WKT)格式指定。不过,出于便利性和历史原因,还支持一些额外的格式。总共有六种指定地理点的方式,如下所示:
PUT my-index-000001
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
# 使用 GeoJSON 格式的对象表示的地理点
PUT my-index-000001/_doc/1
{
"text": "Geopoint as an object using GeoJSON format",
"location": {
"type": "Point",
"coordinates": [-71.34, 41.12]
}
}
# 使用 WKT POINT 原语表示的地理点,格式为:"POINT(lon lat)"
PUT my-index-000001/_doc/2
{
"text": "Geopoint as a WKT POINT primitive",
"location" : "POINT (-71.34 41.12)"
}
# 使用带 'lat' 和 'lon' 键的对象表示的地理点
PUT my-index-000001/_doc/3
{
"text": "Geopoint as an object with 'lat' and 'lon' keys",
"location": {
"lat": 41.12,
"lon": -71.34
}
}
# 使用数组表示的地理点,格式为:[ lon, lat]
PUT my-index-000001/_doc/4
{
"text": "Geopoint as an array",
"location": [ -71.34, 41.12 ]
}
# 使用字符串表示的地理点,格式为:"lat,lon"
PUT my-index-000001/_doc/5
{
"text": "Geopoint as a string",
"location": "41.12,-71.34"
}
# 使用 geohash 表示的地理点
PUT my-index-000001/_doc/6
{
"text": "Geopoint as a geohash",
"location": "drm3btev3e86"
}
# 一个 geo-bounding box 查询,查找落在框内的所有地理点
GET my-index-000001/_search
{
"query": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 42,
"lon": -72
},
"bottom_right": {
"lat": 40,
"lon": -74
}
}
}
}
}
以数组或字符串表示的地理点
请注意,字符串形式的地理点顺序为 lat,lon,而数组形式的地理点、GeoJSON 和 WKT 的顺序则相反:lon,lat。
这是历史原因造成的。地理学家传统上先写纬度后写经度,而较新的地理数据格式(如 GeoJSON 和 Well-Known Text)为了符合数学上 x 在 y 之前的惯例,将经度排在纬度之前(东经先于北纬)。
一个点可以用 geohash 表示。Geohash 是将纬度和经度的比特交错编码后的 base32 编码字符串。geohash 中的每个字符都会增加 5 位精度,因此哈希越长,精度越高。出于索引目的,geohash 会被转换为经纬度对。在此过程中只使用前 12 个字符,因此在 geohash 中指定超过 12 个字符并不会提高精度。这 12 个字符提供 60 位精度,应能将可能的误差降低到 2 厘米以内。
geo_point 字段的参数
geo_point 字段接受以下参数:
ignore_malformed(可选,Boolean)如果为true,则忽略格式错误的地理点。如果为false(默认),格式错误的地理点会抛出异常并拒绝整个文档。如果地理点的纬度超出 -90 ≤ 纬度 ≤ 90 的范围,或经度超出 -180 ≤ 经度 ≤ 180 的范围,则视为格式错误。注意,如果使用了script参数,则无法设置此项。ignore_z_value(可选,Boolean)如果为true(默认),则接受三维点(存储在 source 中),但只索引纬度和经度值;第三维会被忽略。如果为false,包含纬度和经度(二维)以外值的地理点会抛出异常并拒绝整个文档。注意,如果使用了script参数,则无法设置此项。index(可选,Boolean)该字段是否应该可以快速搜索?接受true(默认)和false。只启用doc_values的字段仍然可以查询,只是速度较慢。null_value(可选,字符串)接受一个地理点值,用于替换任何显式的null值。默认为null,表示该字段被视为缺失。注意,如果使用了script参数,则无法设置此项。on_script_error(可选,枚举)定义当script参数定义的脚本在索引时抛出错误时该怎么办。接受fail(默认),它会导致整个文档被拒绝;以及continue,它会将该字段记录到文档的_ignored元数据字段中并继续索引。只有同时设置了script字段时才能设置此参数。script(可选,字符串)如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果输入文档中为该字段设置了值,文档将被拒绝并返回错误。脚本的格式与其运行时字段等效格式相同,并且应输出一对(lat, lon)double 值表示的点。
在脚本中使用地理点
在脚本中访问地理点的值时,该值以 GeoPoint 对象的形式返回,允许分别访问 .lat 和 .lon 值:
def geopoint = doc['location'].value;
def lat = geopoint.lat;
def lon = geopoint.lon;
出于性能考虑,最好直接访问 lat/lon 值:
def lat = doc['location'].lat;
def lon = doc['location'].lon;
合成 _source
合成 source 可能会对 geo_point 字段进行排序(先按纬度,再按经度),并将其缩减到存储精度。例如:
PUT idx
{
"settings": {
"index": {
"mapping": {
"source": {
"mode": "synthetic"
}
}
}
},
"mappings": {
"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}
]
}