Jérémy
Jérémy

Reputation: 111

Query geo distance on elasticsearch with dynamic distance

I am facing an issue with Elasticsearch. I would like use the geo distance feature to fetch all the item located N km maximum from a given localization.

Here is my DB schema:

{
    "user_id": "abcde",
    "pin" : {
       "location" : {
           "lat" : 40.12,
           "lon" : -71.34
        }
    },
    "is_active": true,
    "action_zone": 50
}

I have this query which works pretty well:

{
    "query": {
        "bool" : {
            "must" :
                [{
                    "term": {
                        "is_active": True
                    }
                }],
            "filter" : {
                "geo_distance" : {
                    "distance" : "200km",
                    "pin.location" : {
                        "lat" : 40,
                        "lon" : -70
                    }
                }
            }
        }
    }
}

Now, I would like to modify this query a bit to replace dynamically the distance (200km in my example) by the value "action_zone" of each item of in the DB.

That would be great if someone could help me. :)

Upvotes: 1

Views: 2261

Answers (2)

Jérémy
Jérémy

Reputation: 111

I found the solution using a script :D Thanks anyway !

{
"query": {
    "bool" : {
        "must" :
            [{
                "term": {
                    "is_active": True
                }
            },{
                "script" : {
                    "script" : {
                        "params": {
                            "lat": 40.8,
                            "lon": -70.1
                        },
                        "source": "doc['location'].arcDistance(params.lat, params.lon) / 1000 < doc['action_zone'].value",
                        "lang": "painless"
                    }
                }
            }]
        }
    }
}

}

Doc: https://www.elastic.co/guide/en/elasticsearch/reference/6.1/query-dsl-script-query.html

Upvotes: 4

Val
Val

Reputation: 217274

Unfortunately, the geo_distance query doesn't allow to use scripting in order to specify a dynamic distance. What you could do, however, would be to use a terms aggregation on the action_zone field so as to bucket all your documents within a specific action zone.

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "is_active": True
          }
        }
      ],
      "filter": {
        "geo_distance": {
          "distance": "200km",
          "pin.location": {
            "lat": 40,
            "lon": -70
          }
        }
      }
    }
  },
  "aggs": {
    "zones": {
      "terms": {
        "field": "action_zone"
      }
    }
  }
}

Otherwise, you could also use a range aggregation on the action_zone field with a few specific distances:

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "is_active": "True"
          }
        }
      ],
      "filter": {
        "geo_distance": {
          "distance": "200km",
          "pin.location": {
            "lat": 40,
            "lon": -70
          }
        }
      }
    }
  },
  "aggs": {
    "zones": {
      "range": {
        "field": "action_zone",
        "ranges": [
          {
            "to": 50
          },
          {
            "from": 50,
            "to": 100
          },
          {
            "from": 100,
            "to": 150
          },
          {
            "from": 150
          }
        ]
      }
    }
  }
}

Upvotes: 1

Related Questions