I need to match a field's list to see if at least one term is there from another list. In other words, my Es stored item has a list of "categories" that it fits in. I need to pass up a list of categories to include in the search. I want to get all items that have in their list of categories one or more of the categories from the list of categories I am including in the search.
I have found that this code does as I want:
...
.Must(qs => qs
.TermsSet(t => t
.Field(tf => tf.categories)
.Terms(searchCategories)
.MinimumShouldMatchScript(ss => ss.Source("1"))
)
)
...
But it seems really strange to put a script of "1" in. It feels like I may be missing a more simple way to make this happen. Are my suspicions correct? Is there a better way to do this?
Update
The above code produces this es request:
...
"must":[
{
"terms_set":{
"categories":{
"terms":[1],
"minimum_should_match_script":{"source":"1"}
}
}
}
]
...
Where terms
is the searchCategories
list
Specifying a source of "1"
for the terms set
query minimum should match script field will be the return value of the executed Painless script that determines the minimum number of terms that should match. The script can of course be more complex than returning a single value per document, allowing you to come up with more complex matching requirements for use cases such as attribute based access control.
If you only need any one term of a list of provided terms to match, then you could simply use the terms
query
var searchCategories = new [] {1 };
var searchResponse = client.Search<MyDocument>(s => s
.Query(q => +q
.Terms(t => t
.Field(f => f.categories)
.Terms(searchCategories)
)
)
);
which would yield
{
"query": {
"bool": {
"filter": [
{
"terms": {
"categories": [
1
]
}
}
]
}
}
}
The unary +
overloaded operator in the query is a feature of NEST that makes writing bool queries a little more terse.