Points Closest to the Origin

🏡 Home 📖 Chapter Home 👈 Prev 👉 Next
⚡  ElasticsearchBook.com is crafted by Jozef Sorocin and powered by:

Geo Recap

As we've established in From the Viewport to the Query, any rectangle or bounding box can be targeted using the geo_bounding_box query.
Similarly, any polygon (incl. polygon circles) can be targeted through the geo_polygon query.
But what if we want all points that lie within a certain distance from an origin point? Think the nearest restaurants, the closest Uber driver, etc. That's what the geo_distance query is for.

Use Case: Restaurants Within 0.5 Miles

I want to retrieve restaurants that serve pizza and lie within 0.5 miles of an origin geo point. I also want to give precedence to those that are closer to the origin:
Imaginary Restaurants in Midtown Manhattan. Map courtesy of http://geojson.io/
Imaginary Restaurants in Midtown Manhattan. Map courtesy of http://geojson.io/

Approach

Let's first set up an index:
PUT restaurants
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      },
      "menu": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}
Then index a few restaurants:
POST restaurants/_doc
{
  "name": "French Eatery",
  "location": [-74.00620, 40.73981],
  "menu": [
    "european",
    "french",
    "pizza"
  ]
}

POST restaurants/_doc
{
  "name": "Flatiron Streetfood",
  "location": [-73.99500, 40.74039],
  "menu": [
    "pizza",
    "kebab"
  ]
}
 
We'll first apply a simple match query to target pizza restaurants:
{
  "match": {
    "menu": "pizza"
  }
}
Next, we'll be utilizing a geo_distance query but will need to keep in mind that it's a purely boolean, constant-score query — meaning it'll assign a score of 1 to any docs it matches and filter out those that are too far away:
{
  "geo_distance": {
    "distance": "0.5mi",
    "location": [-73.9982, 40.7388]
  }
}
So on top of that, we'll apply a decay function_score query which is a fancy way of saying "the further one moves from the origin, the lower the location's score":
{
  "function_score": {
    "functions": [
      {
        "exp": {
          "location": {
            "origin": [-73.9982, 40.7388],
            "scale": "0.5mi"
          }
        }
      }
    ]
  }
}

Already purchased? Sign in here.