NEW

Pulse 2025 Product Roundup: From Monitoring to AI-Native Control Plane

Elasticsearch geo_point Field Type: Coordinate Formats, Queries, and Indexing

The geo_point field type stores a single latitude/longitude pair per value and indexes it for distance, bounding-box, polygon, grid-aggregation, and geo-shape-style spatial queries. It is the right choice for any data that can be modeled as a point on Earth: store locations, user check-ins, IP-to-coordinate lookups, vehicle telemetry. For lines, polygons, or multi-points use `geo_shape` instead; geo_point cannot represent anything other than a point.

How geo_point Works

Under the hood, geo_point values are encoded as two 32-bit integers (latitude and longitude quantized to ~1 cm precision) and indexed in a per-segment BKD (Block KD) tree. BKD trees give Elasticsearch sub-linear range queries in 2D, which is why geo_distance and geo_bounding_box stay fast even on billions of points. Distance is computed with the Haversine formula by default, accurate to better than 0.5% for distances up to thousands of kilometers.

geo_point accepts five input formats. Mixing them across documents in the same field is legal but is the most common source of "my coordinates look swapped" bugs:

Format Example Coordinate order
Object {"lat": 41.12, "lon": -71.34} Explicit by key
String "41.12,-71.34" lat, lon
Geohash string "drm3btev3e86" n/a
Array [-71.34, 41.12] lon, lat (GeoJSON order)
GeoJSON object {"type": "Point", "coordinates": [-71.34, 41.12]} lon, lat
WKT POINT "POINT (-71.34 41.12)" lon, lat

The array, GeoJSON, and WKT formats follow the GeoJSON convention of longitude first. The object and string formats use latitude first. This asymmetry trips up almost everyone the first time.

PUT stores
{
  "mappings": {
    "properties": {
      "location": { "type": "geo_point" }
    }
  }
}

POST stores/_doc
{ "location": { "lat": 41.12, "lon": -71.34 } }

GET stores/_search
{
  "query": {
    "geo_distance": {
      "distance": "5km",
      "location": { "lat": 41.10, "lon": -71.30 }
    }
  }
}

geo_point Configuration

Parameter Default Notes
ignore_malformed false If true, invalid coordinates are skipped instead of failing the document.
ignore_z_value true If true, drops the third (altitude) coordinate when GeoJSON or WKT supplies one.
null_value none Substitute point for null input.
index true Set to false to store without indexing (no spatial queries possible).
doc_values true Required for aggregations and sorting by distance.
on_script_error fail What to do when a runtime script-mapped geo_point fails.

Out-of-range values (latitude outside [-90, 90] or longitude outside [-180, 180]) fail the indexing operation unless ignore_malformed: true. Don't disable validation in production - bad coordinates downstream of a coordinate-system bug are far harder to debug than an indexing failure.

Common Pitfalls with geo_point

  1. Mixing array (lon, lat) with object/string (lat, lon) in the same field. Half your points end up in the Indian Ocean off Madagascar.
  2. Storing altitude in a geo_point. It silently drops the third value (with ignore_z_value: true); model elevation as a separate numeric field.
  3. Using geo_distance with a very large distance and expecting cheap queries. Beyond a few hundred km the bounding-box prefilter loses selectivity; consider geo_bounding_box first then a distance sort.
  4. Forgetting that sort by _geo_distance is computed in memory per hit. On large result sets this is the dominant query cost.
  5. Indexing geohash strings expecting partial-match queries on the geohash itself. geo_point decodes geohashes to the centroid of the cell - you cannot query "all documents under prefix drm". Use the geohash_grid aggregation instead.

Operating geo_point Workloads

Geo queries are mostly index-bound; BKD trees live off-heap in the page cache and benefit from generous filesystem memory. The slow paths are usually distance sort on large hit counts and high-cardinality geohash-grid aggregations. Pulse tracks geo-query latency separately from regular search load and surfaces when a geo-heavy index is being starved of page cache by other workloads on the same node.

Frequently Asked Questions

Q: What is the correct coordinate order for an Elasticsearch geo_point?
A: It depends on the format. Object form ({"lat": ..., "lon": ...}) and string form ("lat,lon") use latitude first. Array, GeoJSON, and WKT forms use longitude first (lon, lat), matching the GeoJSON specification. Pick one format and use it consistently across all documents in the field.

Q: How accurate are geo_point distance calculations in Elasticsearch?
A: geo_point coordinates are stored quantized to roughly 1 cm precision (~1e-7 degrees). Distance is computed with the Haversine formula, which assumes a spherical Earth and is accurate to better than 0.5% for typical Earth distances. For sub-meter accuracy or geodesic distances on the WGS84 ellipsoid, compute distance outside Elasticsearch.

Q: Can geo_point store altitude or 3D coordinates?
A: No. geo_point is strictly 2D. By default ignore_z_value is true, so a third coordinate in GeoJSON or WKT input is silently dropped. Store altitude in a separate numeric field if you need it.

Q: What's the difference between geo_point and geo_shape?
A: geo_point stores one point per value and indexes it in a BKD tree. geo_shape stores arbitrary geometries - lines, polygons, multi-polygons, circles - and indexes them in a triangle tree (Lucene's LatLonShape). Use geo_shape when documents represent regions or paths, not just locations.

Q: How do I query for documents within a polygon using geo_point?
A: Use the geo_polygon query (deprecated in favor of geo_shape query against a geo_point field). Both work against geo_point fields; the geo_shape query is the recommended path going forward and supports more polygon shapes and operations.

Q: What happens if I index an invalid latitude or longitude?
A: By default the document is rejected with a parsing error citing the out-of-range value. Setting ignore_malformed: true on the mapping causes invalid points to be silently dropped while the rest of the document indexes normally. This is acceptable for noisy ingest pipelines, but you lose visibility into upstream data quality problems.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.