Dynamic Filter Building in Elasticsearch

1.7k views Asked by At

I am building API. I have id,name,price in elasticsearch. Client provides me input json with filters to be applied.

Input 1: Below user is filtering records with id=1 (integer)

{
    "filters": {
        "id":1
    }

}

Input 2: User is querying for records with city=tokyo

{
    "filters": {
        "city":"tokyo"
    }

}

Java code for handling inputs and querying to elastic search

        filters = ipjson.path("filters");
        Iterator<Entry<String, JsonNode>> ite = filters.fields();

        while (ite.hasNext()) {
            Entry<String, JsonNode> ele = ite.next();
            String key = ele.getKey();
            if (ele.getValue().isInt()) {
                andFilter.add(FilterBuilders.termFilter(key, ele.getValue().asInt()))

            } else if (ele.getValue().isTextual()) {
                andFilter.add(FilterBuilders.termFilter(key, ele.getValue().textValue()));
            }


        }

For each key received in filters, I am checking data type of input value.

I want to support all columns. I want a generic solution without checking for input data type.

Input 3:

{
        "filters": {
            "city":"tokyo",
            "id":3,
            "price":134.45
        }

}

Without any handling for each field vs their data type, I want to query above filters in elasticsearch with java API. How would I do that?

Update:

Trying to send all string parameters to elastic search, getting below exception

SearchParseException[[project][4]: from[-1],size[-1]: Parse Failure [Failed to parse source [{"query":{"filtered":{"filter":{"and":{"filters":[{"term":{"id":"\"1\""}}]}}}}}]]]; nested: NumberFormatException[For input string: ""1""]; }
    at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.onFirstPhaseResult(TransportSearchTypeAction.java:233) ~[elasticsearch-1.4.1.jar:na]
    at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$1.onFailure(TransportSearchTypeAction.java:179) ~[elasticsearch-1.4.1.jar:na]
    at org.elasticsearch.search.action.SearchServiceTransportAction$23.run(SearchServiceTransportAction.java:565) ~[elasticsearch-1.4.1.jar:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.7.0_60]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.7.0_60]
1

There are 1 answers

5
Rohith K On

When you use termFilter for FilterBuilder you dont need to specify the values explicitly as this supports all the basic primitive Java types such as (float,int,long,string,object). So just use FilterBuilders.termFilter(key, ele.getValue()) and apache lucene engine takes care of the type.