Geopoint field type

edit

Fields of type geo_point accept latitude-longitude pairs, which can be used:

As with geo_shape and point, geo_point can be specified in GeoJSON and Well-Known Text formats. However, there are a number of additional formats that are supported for convenience and historical reasons. In total there are six ways that a geopoint may be specified, as demonstrated below:

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

Geopoint expressed as an object, in GeoJSON format, with type and coordinates keys.

Geopoint expressed as a Well-Known Text POINT with the format: "POINT(lon lat)"

Geopoint expressed as an object, with lat and lon keys.

Geopoint expressed as an array with the format: [ lon, lat]

Geopoint expressed as a string with the format: "lat,lon".

Geopoint expressed as a geohash.

A geo-bounding box query which finds all geopoints that fall inside the box.

Geopoints expressed as an array or string

Please note that string geopoints are ordered as lat,lon, while array geopoints, GeoJSON and WKT are ordered as the reverse: lon,lat.

The reasons for this are historical. Geographers traditionally write latitude before longitude, while recent formats specified for geographic data like GeoJSON and Well-Known Text order longitude before latitude (easting before northing) in order to match the mathematical convention of ordering x before y.

A point can be expressed as a geohash. Geohashes are base32 encoded strings of the bits of the latitude and longitude interleaved. Each character in a geohash adds additional 5 bits to the precision. So the longer the hash, the more precise it is. For the indexing purposed geohashs are translated into latitude-longitude pairs. During this process only first 12 characters are used, so specifying more than 12 characters in a geohash doesn’t increase the precision. The 12 characters provide 60 bits, which should reduce a possible error to less than 2cm.

Parameters for geo_point fields

edit

The following parameters are accepted by geo_point fields:

ignore_malformed

If true, malformed geopoints are ignored. If false (default), malformed geopoints throw an exception and reject the whole document. A geopoint is considered malformed if its latitude is outside the range -90 ⇐ latitude ⇐ 90, or if its longitude is outside the range -180 ⇐ longitude ⇐ 180. Note that this cannot be set if the script parameter is used.

ignore_z_value

If true (default) three dimension points will be accepted (stored in source) but only latitude and longitude values will be indexed; the third dimension is ignored. If false, geopoints containing any more than latitude and longitude (two dimensions) values throw an exception and reject the whole document. Note that this cannot be set if the script parameter is used.

index

Should the field be quickly searchable? Accepts true (default) and false. Fields that only have doc_values enabled can still be queried, albeit slower.

null_value

Accepts an geopoint value which is substituted for any explicit null values. Defaults to null, which means the field is treated as missing. Note that this cannot be set if the script parameter is used.

on_script_error

Defines what to do if the script defined by the script parameter throws an error at indexing time. Accepts fail (default), which will cause the entire document to be rejected, and continue, which will register the field in the document’s _ignored metadata field and continue indexing. This parameter can only be set if the script field is also set.

script

If this parameter is set, then the field will index values generated by this script, rather than reading the values directly from the source. If a value is set for this field on the input document, then the document will be rejected with an error. Scripts are in the same format as their runtime equivalent, and should emit points as a pair of (lat, lon) double values.

Using geopoints in scripts

edit

When accessing the value of a geopoint in a script, the value is returned as a GeoPoint object, which allows access to the .lat and .lon values respectively:

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

For performance reasons, it is better to access the lat/lon values directly:

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

Synthetic source

edit

Synthetic _source is Generally Available only for TSDB indices (indices that have index.mode set to time_series). For other indices synthetic _source is in technical preview. Features in technical preview may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.

Synthetic source may sort geo_point fields (first by latitude and then longitude) and reduces them to their stored precision. For example:

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

Will become:

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