地理坐标点字段类型

编辑

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

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

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "properties": {
            "location": {
                "type": "geo_point"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    document={
        "text": "Geopoint as an object using GeoJSON format",
        "location": {
            "type": "Point",
            "coordinates": [
                -71.34,
                41.12
            ]
        }
    },
)
print(resp1)

resp2 = client.index(
    index="my-index-000001",
    id="2",
    document={
        "text": "Geopoint as a WKT POINT primitive",
        "location": "POINT (-71.34 41.12)"
    },
)
print(resp2)

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

resp4 = client.index(
    index="my-index-000001",
    id="4",
    document={
        "text": "Geopoint as an array",
        "location": [
            -71.34,
            41.12
        ]
    },
)
print(resp4)

resp5 = client.index(
    index="my-index-000001",
    id="5",
    document={
        "text": "Geopoint as a string",
        "location": "41.12,-71.34"
    },
)
print(resp5)

resp6 = client.index(
    index="my-index-000001",
    id="6",
    document={
        "text": "Geopoint as a geohash",
        "location": "drm3btev3e86"
    },
)
print(resp6)

resp7 = client.search(
    index="my-index-000001",
    query={
        "geo_bounding_box": {
            "location": {
                "top_left": {
                    "lat": 42,
                    "lon": -72
                },
                "bottom_right": {
                    "lat": 40,
                    "lon": -74
                }
            }
        }
    },
)
print(resp7)
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
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    properties: {
      location: {
        type: "geo_point",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    text: "Geopoint as an object using GeoJSON format",
    location: {
      type: "Point",
      coordinates: [-71.34, 41.12],
    },
  },
});
console.log(response1);

const response2 = await client.index({
  index: "my-index-000001",
  id: 2,
  document: {
    text: "Geopoint as a WKT POINT primitive",
    location: "POINT (-71.34 41.12)",
  },
});
console.log(response2);

const response3 = await client.index({
  index: "my-index-000001",
  id: 3,
  document: {
    text: "Geopoint as an object with 'lat' and 'lon' keys",
    location: {
      lat: 41.12,
      lon: -71.34,
    },
  },
});
console.log(response3);

const response4 = await client.index({
  index: "my-index-000001",
  id: 4,
  document: {
    text: "Geopoint as an array",
    location: [-71.34, 41.12],
  },
});
console.log(response4);

const response5 = await client.index({
  index: "my-index-000001",
  id: 5,
  document: {
    text: "Geopoint as a string",
    location: "41.12,-71.34",
  },
});
console.log(response5);

const response6 = await client.index({
  index: "my-index-000001",
  id: 6,
  document: {
    text: "Geopoint as a geohash",
    location: "drm3btev3e86",
  },
});
console.log(response6);

const response7 = await client.search({
  index: "my-index-000001",
  query: {
    geo_bounding_box: {
      location: {
        top_left: {
          lat: 42,
          lon: -72,
        },
        bottom_right: {
          lat: 40,
          lon: -74,
        },
      },
    },
  },
});
console.log(response7);
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"

地理坐标点表示为地理哈希。

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

地理坐标点表示为数组或字符串

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

造成这种情况的原因是历史遗留问题。地理学家传统上在 经度 之前编写 纬度,而最近为地理数据指定的格式(如 GeoJSONWell-Known Text)在 纬度 之前排序 经度(在纵坐标之前排序横坐标),以便与在 y 之前排序 x 的数学约定相匹配。

一个点可以表示为 地理哈希。地理哈希是纬度和经度交错位的 base32 编码字符串。地理哈希中的每个字符都会为精度增加 5 位。因此,哈希越长,精度就越高。对于索引目的,地理哈希被转换为纬度-经度对。在此过程中,仅使用前 12 个字符,因此在地理哈希中指定超过 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;

出于性能原因,最好直接访问 lat/lon 值

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

合成源

编辑

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

合成源可能会对 geo_point 字段进行排序(先按纬度,然后按经度),并将其减少到其存储的精度。例如

resp = client.indices.create(
    index="idx",
    settings={
        "index": {
            "mapping": {
                "source": {
                    "mode": "synthetic"
                }
            }
        }
    },
    mappings={
        "properties": {
            "point": {
                "type": "geo_point"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="idx",
    id="1",
    document={
        "point": [
            {
                "lat": -90,
                "lon": -80
            },
            {
                "lat": 10,
                "lon": 30
            }
        ]
    },
)
print(resp1)
const response = await client.indices.create({
  index: "idx",
  settings: {
    index: {
      mapping: {
        source: {
          mode: "synthetic",
        },
      },
    },
  },
  mappings: {
    properties: {
      point: {
        type: "geo_point",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "idx",
  id: 1,
  document: {
    point: [
      {
        lat: -90,
        lon: -80,
      },
      {
        lat: 10,
        lon: 30,
      },
    ],
  },
});
console.log(response1);
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}
   ]
}