在 elasticsearch 中针对多个值查询嵌套对象属性

Query Nested Object properties against multiple values in elasticsearch

假设我们有嵌套的对象注释,其中包含两个属性标记和组。如果我执行以下查询,那么它会给我想要的结果。

{
  "query": {
    "bool": {
      "must": {
        "nested": {
          "query": {
            "bool": {
              "must": {
                "match": {
                  "comment.tag": {
                    "query": "SPRING",
                    "type": "boolean"
                  }
                }
              },
              "must_not": {
                "match": {
                  "comment.group": {
                    "query": "ABC",
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "path": "comment"
        }
      }
    }
  }
}

但是如果我执行下面的查询,它不会给我想要的结果。

{
  "query": {
    "bool": {
      "must": {
        "nested": {
          "query": {
            "bool": {
              "must": {
                "match": {
                  "comment.tag": {
                    "query": [
                      "SPRING",
                      "HIBERNATE"
                    ],
                    "type": "boolean"
                  }
                }
              },
              "must_not": {
                "match": {
                  "comment.group": {
                    "query": [
                      "ABC",
                      "XYZ"
                    ],
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "path": "comment"
        }
      }
    }
  }
}

这两者之间的区别在于,我针对多个值查询嵌套对象的两个属性。

对于第二个查询,它仅选取提供给搜索的列表中的最后一个值和 returns 结果。

有没有一种方法可以编写查询,我可以在其中指定传递值列表并且所有值都包含在搜索中?

这与嵌套无关query/filter。相反,它是您使用 match query 的方式。它不需要值数组。

实际上有两种方法可以实现您似乎正在尝试的目标。在进入它们之前,我确实想注意 match 查询默认使用 boolean 类型,因此您可以忽略它。

  1. 您可以更改 match 查询以简单地在字符串中提供两个值。顺序无关紧要:

    "bool" : {
      "must" : {
        "match" : {
          "comment.tag" : "SPRING HIBERNATE"
        }
      }
    }
    

    之所以可行,是因为该字段将使用搜索分析器以与对该字段建立索引(默认)的方式相同的方式来标记字符串。因此,假设使用默认的字符串分析器,您最终将搜索 spring hibernate。因为您没有使用词组匹配,所以顺序确实无关紧要。

  2. 另一种方法是使用外部 bool/must 查询显式分隔它们(同样适用于 must_notshould ).因为你希望他们像 ORs 一样对待,所以你需要使用 should 而不是 must 这样:

    "bool" : {
      "should" : [
        {
          "match" : { "company.tag" : "SPRING" }
        },
        {
          "match" : { "company.tag" : "HIBERNATE" }
        }
      ]
    }
    

    注意:如果您还包括 must,则需要将 minimum_should_match 设置为 1(在 bool 对象内部),这样它就不会成为可选的。没有 mustmust_not,它隐式为 1.