Is there an alternative solution to terms "execution": "and" on ES 2.x?


(Luis Roberto Pereira de Paula) #1

Given that I have following document in an index:

PUT /test_index/my_type/1
{
    "id": 1,
    "my_array": ["1", "2", "3", "4"]
}

If I run the following query on ES 1.x, it gives me 0 total hits, as expected:

POST /test_index/my_type/_search
{
    "query": {
        "function_score": {
            "score_mode": "sum",
            "filter": {
                "bool": {
                    "must": {
                        "terms": {
                            "my_array": ["1", "5"],
                            "execution": "and"
                        }
                    }
                }
            }
        }
    },
    "size": 50,
    "from": 0
}

But on ES 2.x, as the execution does not work with terms anymore, what would be the best aproach to rewrite this query? Is there a better option than the following one?

POST /test_index/my_type/_search
{
    "query": {
        "function_score": {
            "score_mode": "sum",
            "filter": {
                "bool": {
                    "must": [{
                        "terms": {
                            "my_array": ["1"]
                        }
                    },
                    {
                        "terms": {
                            "my_array": ["5"]
                        }
                    }]
                }
            }
        }
    },
    "size": 50,
    "from": 0
}

Best Regards,
Luis


(Nik Everett) #2

I'd write it as.

"query": {
  "bool": {
    "filter": [
      { "term": { "my_array": "1" } },
      { "term": { "my_array": "5" } }
    ]
  }
}

I can't speak for why the execution mode is gone. It could have to do with Elasticsearch making a conscious effort to move its queries closer to the queries available in Lucene. And the TermsQuery only supports OR.

Fun fact: its rewritten into a bool query with lots of must not clauses if the number of terms is less than 12 or so because its particular optimizations don't help without a boat load of terms.


(Luis Roberto Pereira de Paula) #3

Thanks for your reply!

Your solution is slightly better!

That would become something like this:

POST /test_index/my_type/_search
{
    "query": {
        "function_score": {
            "score_mode": "sum",
            "filter": {
                "and": {
                    "filter": [
                        { "term": { "my_array": "1" } },
                        { "term": { "my_array": "2" } },
                        { "term": { "my_array": "5" } }
                    ]
                }
            }
        }
    },
    "size": 50,
    "from": 0
}

However, I was looking for a way to pass an array instead of a term for each item. I guess there is no other way.


(Nik Everett) #4

You'd have to make a list of queries, yes. I wouldn't swap bool query for and. Keep bool. and is deprecated. Presumably you need the function_score because you have some function that you aren't adding to the post?


(Luis Roberto Pereira de Paula) #5

You are right! Thanks for the tip. I will use bool. And yes, I have a function here, but function_score is not relevant for the scope of this post.


(system) #6