Search code examples
elasticsearchgeolocation

ElasticSearch filter by geo location with value or null value


I'm adding businesses into ElasticSearch. Some are geo located (lon,lat coordinates), some are online businesses only (no coordinates).

What I'm trying to do is to create a query where I filter businesses with a given geo position and a radius. And I would like to include thoses online businesses (without geo coordinates).

Do you have any ideas how to do that?

I've tried this:

GET /organizations/_search
{
  "query": {
    "bool" : {
      "must_not": {
        "exists": {
          "field": "geocoords"
        }
      },
      "filter" : {
        "geo_distance" : {
          "distance" : "200km",
          "geocoords" : {
            "lon": -73.57,
            "lat": 45.45
          }
        }
      }
    }
  }
}

But I got no result:

{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

This is the data I have:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "organizations",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "is_active" : true,
          "name": "Compagny Inc.",
          "geocoords" : {
            "lon" : -73.5761003,
            "lat" : 45.4560316
          }
        }
      }
    ]
  }
}

Any tips or advices? Thank you.


Solution

  • The current query is mutually exclusive -- you first filter out valid coords and then perform a radial search...

    Instead, you may want a logical OR -- either in the radius OR no coords at all:

    GET organizations/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "bool": {
                "filter": {
                  "geo_distance": {
                    "distance": "200km",
                    "geocoords": {
                      "lon": -73.57,
                      "lat": 45.45
                    }
                  }
                }
              }
            },
            {
              "bool": {
                "must_not": [
                  {
                    "exists": {
                      "field": "geocoords"
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }