Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elasticsearch QueryBuilder Match Multiple Terms

Given JSON in ES index in the following format:

{
    "pin": {
        "id": 123,
        "location": {
            "lat": 456,
            "lon":-789
        }
    }
}

The following gets the document matching the id field:

client.prepareSearch("index_name")
        .setTypes("pin")
        .setQuery(QueryBuilders.termQuery("id", 123))
        .execute()
        .actionGet();

Instead, I 'm trying to match multiple fields, ie. (location.lat, location.lon).

QueryBuilders.termQuery(); // accepts only a single term

Tried few alternatives but none of it seems to work, eg:

QueryBuilder queryBuilder = QueryBuilders.boolQuery()
        .must(QueryBuilders.termQuery("location.lat", 456))
        .must(QueryBuilders.termQuery("location.lon", -789));

client.prepareSearch("index_name")
        .setTypes("pin")
        .setQuery(queryBuilder)
        .execute()
        .actionGet();
like image 280
ahmedyha Avatar asked May 27 '12 11:05

ahmedyha


2 Answers

By default, a geo_point field is not indexed as two fields (location.lat and location.lon), it's indexed as a single field that contains both latitude and longitude.

You can turn on indexing of latitude and longitude by turning on the lat_lon mapping option. However, in your example, the values for latitude and longitude are too large. So, they are normalized, converted to double and indexed as -84.0 and -69.0 instead of 456 and -789. So, if you will enable lat_lon and replace the value in the queries, you should be able to get the results.

Please note that values for latitude and longitude are converted to double before indexing. So using term queries might not be very practical in the long term since you will have to always take rounding errors into consideration. It might be more useful to use range queries or elasticsearch geospatial queries instead.

like image 189
imotov Avatar answered Sep 22 '22 03:09

imotov


Check out the bool query in ElasticSearch, you should be able to specify must, should or should_not to get the appropriate mixture of and/or for your query.

like image 30
thnetos Avatar answered Sep 19 '22 03:09

thnetos