【问题标题】:Elasticsearch array property must contain given array itemsElasticsearch 数组属性必须包含给定的数组项
【发布时间】:2015-11-02 04:31:15
【问题描述】:

我的文件看起来像:

{
    "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 都包含 tag1 或 tag3,因此我将“示例 1”和“示例 2”都作为匹配项。通过查看术语的文档,我发现术语实际上是一个包含查询。

在这种情况下,如何确保示例 2 是使用 tag1 和 tag3 查询时的唯一命中?

【问题讨论】:

  • 您需要至少特定的 2 个元素,或者具有该确切数组的文档?

标签: arrays elasticsearch term


【解决方案1】:

您需要通过将"execution": "and" 添加到terms 过滤器来将execution mode 设置为“和”,以便所有术语都必须包含在文档中被视为匹配

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

这实际上与使用所有术语的结合构建bool must 过滤器相同,但形式更紧凑。

【讨论】:

  • 现在应该使用must 查询来编写,因为filtered 查询自ES v5.0 起已被弃用,如here 所述
  • @Louis 整个查询需要以完全不同的方式编写 5 年以后,因为术语查询的执行模式也消失了
【解决方案2】:

对于那些在 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 上下文使其成为过滤器。

阅读更多here

【讨论】:

  • 我不确定在什么情况下minimum_should_match 可能会被弃用,但谷歌只会告诉我minimum_number_should_match 发生的情况。
【解决方案3】:

您可以设置minimum_should_match 以匹配您的数组:

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

【讨论】:

    猜你喜欢
    • 2019-06-10
    • 2014-02-05
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 2017-05-06
    相关资源
    最近更新 更多