ElasticSearch 5.x should query vs filtering


(Blade Watcher) #1

I have a problem with results come from an ES query. Filtering a query gives some confusing results, and I don't know how to overcome of it. So:

{
    "query":{
        "bool":{
            "should":[
            {
                "multi_match":
                {
                    "query":"searchquery",
                    "operator":"and",
                    "fields":["Name", "Description", "Text"]
                }
            },
            {
                "bool":{
                    "must": [
                        {"terms": {"Id": [1, 2]}},
                        {"term": {"_type": "Project"}}
                    ]
                }
            }
            ]
        }
    }
}

What I want here is: get all records whose Name, or Description, or Text is match the query OR all Projects (it's a _type in the mapping), whose Id 1, or 2. The results seems exactly what I expected, I got eg: 5 hits, 2 Contact _type (matches "searchquery"), 1 Project (matches "searchquery") and 2 projects with Id 1, or 2. Good!

But I have some authorization, so not all users access all Modules (Projects have another field eg: ModuleId).

So I want to restrict the results to specific ModuleIds:

{
    "query":{
        "bool":{
            "should":[
            {
                "multi_match":
                {
                    "query":"searchquery",
                    "operator":"and",
                    "fields":["Name", "Description", "Text"]
                }
            },
            {
                "bool":{
                    "must": [
                        {"terms": {"Id": [1, 2]}},
                        {"term": {"_type": "Project"}}
                    ]
                }
            }
            ],
            "filter": [
                {"terms": {"ModuleId": [9, 5]}}
            ]
        }
    }
}

And boom! In the result I got all, whose match the above query and all Projects with ModuleId 9, or 5. What I want is to narrow the results, not broaden them. I've tried many combinations with should, must, filter(bool filter as well). I've also tried post_filter which "magically" gives me the expected result, but I have some aggregations as well (not in this example), sot it is not an option.


(Isabel Drost-Fromm) #2

I think the easiest would be to add a minimum_should_match parameter set to 1 to your outer bool query.

Here's an explanation of the parameter:

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-minimum-should-match.html

The reason for the behaviour you are seeing is explained in more detail here which also has a hint towards the minimum_should_match docs:

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html

"The clause (query) should appear in the matching document. In a boolean query with no must or filter clauses, one or more should clauses must match a document."

Hope this helps,
Isabel


(Blade Watcher) #3

Works, like a charm, thank you!


(system) #4

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.