Link Search Menu Expand Document Documentation Menu

布尔查询

布尔 (bool) 查询可以将多个查询子句组合成一个高级查询。这些子句通过布尔逻辑组合,以查找结果中返回的匹配文档。

bool 查询中使用以下查询子句

子句 行为
must 逻辑 and 运算符。结果必须匹配此子句中的所有查询。
must_not 逻辑 not 运算符。所有匹配项都将从结果中排除。如果 must_not 包含多个子句,则只返回不匹配这些子句中任何一个的文档。例如,"must_not":[{clause_A}, {clause_B}] 等同于 NOT(A OR B)
should 逻辑 or 运算符。结果必须匹配至少一个查询。匹配的 should 子句越多,文档的相关性得分越高。您可以使用 minimum_should_match 参数设置必须匹配的最小查询数。如果查询包含 mustfilter 子句,则默认的 minimum_should_match 值为 0。否则,默认的 minimum_should_match 值为 1。
filter 逻辑 and 运算符,首先应用于减少数据集,然后再应用查询。过滤器子句中的查询是“是”或“否”选项。如果文档匹配查询,则返回结果;否则,不返回。过滤器查询的结果通常会缓存,以实现更快返回。使用过滤器查询根据精确匹配、范围、日期或数字来过滤结果。

布尔查询具有以下结构

GET _search
{
  "query": {
    "bool": {
      "must": [
        {}
      ],
      "must_not": [
        {}
      ],
      "should": [
        {}
      ],
      "filter": {}
    }
  }
}

例如,假设您在 OpenSearch 集群中索引了莎士比亚的全部作品。您想要构建一个满足以下要求的单个查询

  1. text_entry 字段必须包含单词 love,并且应包含 lifegrace
  2. speaker 字段不得包含 ROMEO
  3. 将这些结果过滤到剧本 Romeo and Juliet,而不影响相关性得分。

这些要求可以组合到以下查询中

GET shakespeare/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "text_entry": "love"
          }
        }
      ],
      "should": [
        {
          "match": {
            "text_entry": "life"
          }
        },
        {
          "match": {
            "text_entry": "grace"
          }
        }
      ],
      "minimum_should_match": 1,
      "must_not": [
        {
          "match": {
            "speaker": "ROMEO"
          }
        }
      ],
      "filter": {
        "term": {
          "play_name": "Romeo and Juliet"
        }
      }
    }
  }
}

响应包含匹配的文档

{
  "took": 12,
  "timed_out": false,
  "_shards": {
    "total": 4,
    "successful": 4,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 11.356054,
    "hits": [
      {
        "_index": "shakespeare",
        "_id": "88020",
        "_score": 11.356054,
        "_source": {
          "type": "line",
          "line_id": 88021,
          "play_name": "Romeo and Juliet",
          "speech_number": 19,
          "line_number": "4.5.61",
          "speaker": "PARIS",
          "text_entry": "O love! O life! not life, but love in death!"
        }
      }
    ]
  }
}

如果您想识别这些子句中哪个实际导致了匹配结果,请使用 _name 参数命名每个查询。要添加 _name 参数,请将 match 查询中的字段名称更改为对象

GET shakespeare/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "text_entry": {
              "query": "love",
              "_name": "love-must"
            }
          }
        }
      ],
      "should": [
        {
          "match": {
            "text_entry": {
              "query": "life",
              "_name": "life-should"
            }
          }
        },
        {
          "match": {
            "text_entry": {
              "query": "grace",
              "_name": "grace-should"
            }
          }
        }
      ],
      "minimum_should_match": 1,
      "must_not": [
        {
          "match": {
            "speaker": {
              "query": "ROMEO",
              "_name": "ROMEO-must-not"
            }
          }
        }
      ],
      "filter": {
        "term": {
          "play_name": "Romeo and Juliet"
        }
      }
    }
  }
}

OpenSearch 返回一个 matched_queries 数组,其中列出了与这些结果匹配的查询

"matched_queries": [
  "love-must",
  "life-should"
]

如果移除不在该列表中的查询,您仍会看到完全相同的结果。通过检查哪些 should 子句匹配,您可以更好地理解结果的相关性得分。

您还可以通过嵌套 bool 查询来构建复杂的布尔表达式。例如,使用以下查询在剧本 Romeo and Juliet 中查找匹配 (love OR hate) AND (life OR grace) 的 text_entry 字段

GET shakespeare/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "should": [
              {
                "match": {
                  "text_entry": "love"
                }
              },
              {
                "match": {
                  "text": "hate"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "text_entry": "life"
                }
              },
              {
                "match": {
                  "text": "grace"
                }
              }
            ]
          }
        }
      ],
      "filter": {
        "term": {
          "play_name": "Romeo and Juliet"
        }
      }
    }
  }
}

响应包含匹配的文档

{
  "took": 10,
  "timed_out": false,
  "_shards": {
    "total": 2,
    "successful": 2,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 11.37006,
    "hits": [
      {
        "_index": "shakespeare",
        "_type": "doc",
        "_id": "88020",
        "_score": 11.37006,
        "_source": {
          "type": "line",
          "line_id": 88021,
          "play_name": "Romeo and Juliet",
          "speech_number": 19,
          "line_number": "4.5.61",
          "speaker": "PARIS",
          "text_entry": "O love! O life! not life, but love in death!"
        }
      }
    ]
  }
}
剩余 350 字符

有问题?

想贡献?