Elasticsearch的数组属性必须包含给定的数组项。

8

我有一些类似于以下格式的文档:

{
    "tags" => [
        "tag1",
        "tag2",
    ],
    "name" => "Example 1"
}

{
    "tags" => [
        "tag1",
        "tag3",
        "tag4"
    ],
    "name" => "Example 2"
}

我现在想要做一个术语搜索,给定的数组可能如下:

[tag1, tag3]

期望击中应该在哪里:

{
    "tags" => [
        "tag1",
        "tag3",
        "tag4"
    ],
    "name" => "Example 2"
}

然而,当我执行以下查询时:

GET _search
{
    "query": {
        "filtered": {
           "query": {
               "match_all": {}
           },
           "filter": {
               "bool": {
                   "must": [
                      {
                          "terms": {
                             "tags": [
                                "tag1",
                                "tag3"
                             ]
                          }
                      }
                   ]
               }
           }
       }
    }
}

我得到了"示例1"和"示例2"的结果,因为两个示例中都包含标签1或标签3。根据terms的文档,我发现terms实际上是一个包含查询。

在这种情况下,我如何确保在查询标记1和标记3时,只有"示例2"是命中的?


你需要至少特定的2个元素,还是具有完全相同数组的文档? - Slam
3个回答

6

如果你在2020年看到这篇文章,你可能已经注意到minimum_should_match早已过时。

现在有一种替代方法可以使用,就是使用terms_set

例如:

{
  "query": {
    "terms_set": {
      "programming_languages": {
        "terms": [ "c++", "java", "php" ],
        "minimum_should_match_field": "required_matches"
      }
    }
  }
}


上述示例假设存在一个称为“required_matches”的字段,其中包含一个整数,定义了应该有多少匹配项。
更有用的是替代字段minimum_should_match_script
请参见下面的示例:
{
  "query": {
    "terms_set": {
      "programming_languages": {
        "terms": [ "c++", "java", "php" ],
        "minimum_should_match_script": {
          "source": "2"
        },
      }
    }
  }
}

您可以始终在filter上下文中使用terms set query作为过滤器。

了解更多信息,请点击这里


1
我不确定minimum_should_match在什么情况下可能被弃用,但是谷歌只会显示minimum_number_should_match被弃用的情况。 - Noumenon

4
你需要将 execution mode 设置为 "and",方法是在 terms 过滤器中添加 "execution": "and",这样所有术语都必须包含在文档中才能被视为匹配。
GET _search
{
   "query": {
      "filtered": {
         "query": {
            "match_all": {}
         },
         "filter": {
            "terms": {
               "tags": [
                  "tag1",
                  "tag3"
               ],
               "execution": "and"
            }
         }
      }
   }
}

这实际上相当于使用所有术语的连词建立一个bool must过滤器,但以更紧凑的形式呈现。

现在应该使用must查询,因为ES v5.0以后的版本弃用了filtered查询,详情请参见此处 - Louis
1
@Louis,从5开始整个查询需要以完全不同的方式编写,因为术语查询的执行模式也已经消失了。 - Russ Cam

0
您可以设置minimum_should_match来匹配您的数组:
{
    "query": {
        "filtered": {
           "query": {
               "match_all": {}
           },
           "filter": {
               "bool": {
                   "must": [
                      {
                          "terms": {
                             "tags": ["tag1","tag3"],
                             "minimum_should_match": 2
                          }
                      }
                   ]
               }
           }
       }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接