【问题标题】:Elasticsearch match complete array of termsElasticsearch 匹配完整的术语数组
【发布时间】:2020-04-27 03:25:43
【问题描述】:

我需要用 elasticsearch 匹配一个完整的术语数组。 只应返回具有相同元素的数组的文档。 文档数组中不应有更多元素或元素子集。 元素的顺序无关紧要。

例子:

 filter:
   id: ["a", "b"]

 documents:  
   id: ["a", "b"] -> match  
   id: ["b", "a"] -> match  
   id: ["a"] -> no match  
   id: ["a", "b", "c"] -> no match  

最终我想使用 Java High Level REST Client 来实现查询,不过弹性搜索 dsl 的示例也可以。

【问题讨论】:

    标签: java elasticsearch elasticsearch-dsl


    【解决方案1】:

    虽然本机似乎不支持此功能,但您可以继续使用脚本过滤器来实现此行为,如下所示:

    GET your_index/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "script": {
                "script": "doc['tags'].values.length == 2"
              }
            },
            {
              "term": {
                "tags": {
                  "value": "a"
                }
              }
            },
            {
              "term": {
                "tags": {
                  "value": "b"
                }
              }
            }
          ]
        }
      }
    }
    

    脚本过滤器通过数组大小限制搜索结果,而术语过滤器指定该数组的值。确保在标签 field 上启用 fielddata 以便在其上执行脚本。

    【讨论】:

      【解决方案2】:

      我想提出一些建议,以防止您在您的要求发生变化时立即维持一长串“必须”条件(例如,假设您有一个包含六个项目的数组要匹配)。我将依赖脚本查询,它可能看起来设计过度,但很容易从中创建搜索模板 (https://www.elastic.co/guide/en/elasticsearch/reference/7.5/search-template.html)。

      {
      "query": {
          "bool": {
            "filter": {
              "script": {
                "script": {
                  "source": """
                    def ids = new ArrayList(doc['id.keyword']);
                    def param = new ArrayList(params.terms);
                    def isSameSize = ids.size() == param.size();
                    def isSameContent = ids.containsAll(param);
                    return isSameSize && isSameContent
                  """,
                  "lang": "painless",
                  "params": {
                    "terms": [ "a", "b" ]
                  }
                }
              }
            }
          }
        }
      }
      

      这样,您唯一需要更改的是terms 参数的值。

      【讨论】:

        猜你喜欢
        • 2022-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-26
        • 1970-01-01
        • 2018-04-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多