I have a set of documents like
{
tags:['a','b','c']
// ... a bunch properties
}
As stated in the title: Is there a way to filter all documents containing any of given tags using Nest ?
For instance, the record above would match ['c','d']
Or should I build multiple "OR"s manually ?
There's also terms query which should save you some work. Here example from docs:
Under hood it constructs boolean should. So it's basically the same thing as above but shorter.
There's also a corresponding terms filter.
So to summarize your query could look like this:
With greater number of tags this could make quite a difference in length.
Whilst this an old question, I ran into this problem myself recently and some of the answers here are now deprecated (as the comments point out). So for the benefit of others who may have stumbled here:
A
term
query can be used to find the exact term specified in the reverse index:From the documenation https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html
Alternatively you can use a
terms
query, which will match all documents with any of the items specified in the given array:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html
One gotcha to be aware of which caught me out - how you define the document also makes a difference. If the field you're searching in has been indexed as a text type then Elasticsearch will perform a full text search (i.e using an
analyzed
string).If you've indexed the field as a keyword then the a keyword search using a 'non-analyzed' string is performed. This can has a massive practical impact as Analyzed strings are pre-processed (lowercased, punctuation dropped etc.) See (https://www.elastic.co/guide/en/elasticsearch/guide/master/term-vs-full-text.html)
Edit: The bitset stuff below is maybe an interesting read, but the answer itself is a bit dated. Some of this functionality is changing around in 2.x. Also Slawek points out in another answer that the
terms
query is an easy way to DRY up the search in this case. Refactored at the end for current best practices. —nzYou'll probably want a Bool Query (or more likely Filter alongside another query), with a
should
clause.The bool query has three main properties:
must
,should
, andmust_not
. Each of these accepts another query, or array of queries. The clause names are fairly self-explanatory; in your case, theshould
clause may specify a list filters, a match against any one of which will return the document you're looking for.From the docs:
Here's an example of what that Bool query might look like in isolation:
And here's another example of that Bool query as a filter within a more general-purpose Filtered Query:
Whether you use Bool as a query (e.g., to influence the score of matches), or as a filter (e.g., to reduce the hits that are then being scored or post-filtered) is subjective, depending on your requirements.
It is generally preferable to use Bool in favor of an Or Filter, unless you have a reason to use And/Or/Not (such reasons do exist). The Elasticsearch blog has more information about the different implementations of each, and good examples of when you might prefer Bool over And/Or/Not, and vice-versa.
Elasticsearch blog: All About Elasticsearch Filter Bitsets
Update with a refactored query...
Now, with all of that out of the way, the
terms
query is a DRYer version of all of the above. It does the right thing with respect to the type of query under the hood, it behaves the same as thebool
+should
using theminimum_should_match
options, and overall is a bit more terse.Here's that last query refactored a bit: