我有一套像
这样的文件{
tags:['a','b','c']
// ... a bunch properties
}
如标题所述:有没有办法使用Nest过滤包含任何给定标签的所有文档?
例如,上面的记录会匹配[' c',' d']
或者我应该手动构建多个" OR"
答案 0 :(得分:51)
还有terms query这可以为你节省一些工作。这里来自docs的例子:
{
"terms" : {
"tags" : [ "blue", "pill" ],
"minimum_should_match" : 1
}
}
在引擎盖下,它构造了布尔值。所以它与上面的基本相同,但更短。
还有相应的terms filter。
总结一下您的查询可能如下所示:
{
"filtered": {
"query": {
"match": { "title": "hello world" }
},
"filter": {
"terms": {
"tags": ["c", "d"]
}
}
}
}
随着标签数量的增加,这可能会产生很大的差异。
答案 1 :(得分:41)
编辑:下面的bitset内容可能是一个有趣的读物,但答案本身有点陈旧。其中一些功能在2.x中发生了变化。另外,Slawek在另一个答案中指出terms
查询是一种在这种情况下干扰搜索的简单方法。在最后重构当前的最佳实践。 -nz
您可能希望Bool Query(或更可能Filter与另一个查询一起使用),并带有should
子句。
bool查询有三个主要属性:must
,should
和must_not
。其中每个都接受另一个查询或查询数组。条款名称相当不言自明;在您的情况下,should
子句可以指定列表过滤器,与任何一个匹配将返回您正在查找的文档。
来自文档:
在没有
must
子句的布尔查询中,一个或多个should
子句必须与文档匹配。可以使用minimum_should_match
参数设置要匹配的最小should子句数。
以下是Bool查询可能孤立的示例:
{
"bool": {
"should": [
{ "term": { "tag": "c" }},
{ "term": { "tag": "d" }}
]
}
}
这是Bool查询作为更通用的Filtered Query中的过滤器的另一个例子:
{
"filtered": {
"query": {
"match": { "title": "hello world" }
},
"filter": {
"bool": {
"should": [
{ "term": { "tag": "c" }},
{ "term": { "tag": "d" }}
]
}
}
}
}
您是否使用Bool作为查询(例如,影响匹配的分数),或者作为过滤器(例如,减少随后被评分或后过滤的命中)是主观的,这取决于您的要求。
通常最好使用Bool而不是Or Filter,除非你有理由使用And / Or / Not(这样的理由确实存在)。 Elasticsearch博客提供了有关每种实现的不同实现的更多信息,以及何时可能更喜欢Bool over And / Or / Not的好例子,反之亦然。
Elasticsearch博客:All About Elasticsearch Filter Bitsets
使用重构查询进行更新...
现在,在所有 的情况下,terms
查询是上述所有内容的DRYer版本。它在底层的查询类型方面是正确的,它使用bool
选项与should
+ minimum_should_match
的行为相同,总体上更简洁一些。
这是最后一个查询重构了一点:
{
"filtered": {
"query": {
"match": { "title": "hello world" }
},
"filter": {
"terms": {
"tag": [ "c", "d" ],
"minimum_should_match": 1
}
}
}
}
答案 2 :(得分:3)
尽管这是一个古老的问题,但我最近自己遇到了这个问题,并且不赞成此处的某些答案(正如评论所指出的那样)。因此,为了其他可能在这里绊倒的人的利益:
term
查询可用于查找在反向索引中指定的确切术语:
{
"query": {
"term" : { "tags" : "a" }
}
从文档https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html
或者,您可以使用terms
查询,该查询将使所有文档与给定数组中指定的任何项目匹配:
{
"query": {
"terms" : { "tags" : ["a", "c"]}
}
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html
一个棘手的问题使我感到困惑-您如何定义文档也有所作为。如果您要搜索的字段已被索引为文本类型,则Elasticsearch将执行全文搜索(即使用analyzed
字符串)。
如果您已将该字段索引为关键字,则将执行使用“未分析”字符串的关键字搜索。在对已分析的字符串进行预处理(小写,删除标点符号等)时,这可能会产生巨大的实际影响。请参阅(https://www.elastic.co/guide/en/elasticsearch/guide/master/term-vs-full-text.html)
为避免这些问题,字符串字段分为两种新类型:应该用于全文搜索的文本和应该用于关键字搜索的关键字。 (https://www.elastic.co/blog/strings-are-dead-long-live-strings)
答案 3 :(得分:0)
您应该使用Terms Query
{
"query" : {
"terms" : {
"tags" : ["c", "d"]
}
}
}
答案 4 :(得分:0)
对于那些在2020年看到此问题的人来说,您可能会注意到在2020年已弃用了公认的答案,但是使用terms_set
和minimum_should_match_script
组合也有类似的方法。
请在SO线程中查看详细答案here