深入学习 ElasticSearch 的搜索(五):bool 查询
深入学习 ElasticSearch 的搜索五bool 查询bool查询用于组合多个查询条件。实际业务中的搜索很少只有一个条件通常会是关键词匹配分类过滤状态过滤时间范围排除某些数据某些条件用于提升排序这些组合条件就需要用bool查询表达。一、bool 查询的基本结构bool查询常见有四类子句mustshouldfiltermust_not示例POSTarticle_search/_search{query:{bool:{must:[],should:[],filter:[],must_not:[]}}}它们的含义不同。二、must必须匹配并参与评分must表示条件必须满足并且会影响_score。例如查询正文包含ElasticSearchPOSTarticle_search/_search{query:{bool:{must:[{match:{content:ElasticSearch}}]}}}如果有多个must条件全部都要满足。POSTarticle_search/_search{query:{bool:{must:[{match:{title:ElasticSearch}},{match:{content:倒排索引}}]}}}这类似title 命中 ElasticSearch 并且 content 命中 倒排索引三、filter必须匹配但不参与评分filter也表示必须满足但它不参与相关性评分。它适合结构化过滤条件例如状态分类作者时间范围是否删除示例POSTarticle_search/_search{query:{bool:{must:[{match:{content:ElasticSearch}}],filter:[{term:{status:published}}]}}}含义是正文要匹配ElasticSearch状态必须是published评分只主要由match决定通常来说状态、分类这类条件应该放在filter而不是must。四、must_not必须不匹配must_not用于排除文档。例如排除草稿POSTarticle_search/_search{query:{bool:{must:[{match:{content:ElasticSearch}}],must_not:[{term:{status:draft}}]}}}含义是正文包含 ElasticSearch并且 status 不能是 draft五、should应该匹配用于提升相关性should表示最好满足。它经常用于提升某些文档的评分。例如POSTarticle_search/_search{query:{bool:{must:[{match:{content:ElasticSearch}}],should:[{match:{title:ElasticSearch}}]}}}含义是正文必须命中ElasticSearch如果标题也命中ElasticSearch相关性更高这很适合搜索排序优化。六、minimum_should_match如果只有should可以用minimum_should_match控制至少要满足几个条件。POSTarticle_search/_search{query:{bool:{should:[{match:{title:ElasticSearch}},{match:{content:倒排索引}},{term:{category:elasticsearch}}],minimum_should_match:2}}}含义是三个 should 条件中至少满足两个。这适合做更灵活的相关内容搜索。七、组合一个真实查询假设后台文章列表有这些条件关键词ElasticSearch分类elasticsearch状态published浏览量大于 100排除作者 ops可以写成POSTarticle_search/_search{query:{bool:{must:[{match:{content:ElasticSearch}}],filter:[{term:{category:elasticsearch}},{term:{status:published}},{range:{views:{gt:100}}}],must_not:[{term:{author:ops}}],should:[{match:{title:ElasticSearch}}]}}}这个查询里must负责主关键词filter负责结构化筛选must_not负责排除should负责提升相关性八、filter 和 must 怎么选可以这样判断如果条件影响“相关不相关”放must。例如标题是否命中关键词正文是否命中关键词如果条件只是“要不要这条数据”放filter。例如状态必须是已发布分类必须是某个分类时间必须在某个范围内用户 ID 必须等于某个值简单记关键词搜索 - must 精确过滤 - filter 排除条件 - must_not 加分条件 - should九、query context 和 filter contextElasticSearch 查询里有两个重要上下文query contextfilter contextmust、should中的查询通常处在 query context会回答这篇文档有多相关所以它们会影响_score。filter、must_not中的查询通常处在 filter context会回答这篇文档是否满足条件所以它们不参与相关性评分。这就是为什么状态、分类、时间范围、租户 ID 这类业务约束更适合放在filter中。十、boost 在 bool 中的意义bool本身也可以设置boost。它的含义不是“必须有多个 bool 才有意义”而是当这棵 bool 查询树和其他查询一起参与评分时boost 会影响它在最终_score中的权重。例如POSTarticle_search/_search{query:{bool:{should:[{bool:{must:[{match_phrase:{content:倒排索引}}],boost:3}},{match:{content:ElasticSearch 搜索}}]}}}这里完整短语命中的这棵子查询树会被加权。如果整个查询里只有一个条件而且没有其他评分项可比较那么boost的体感可能不明显。十一、bool 可以嵌套复杂业务查询本质上是一棵查询树bool可以嵌套在另一个bool中。例如POSTarticle_search/_search{query:{bool:{must:[{bool:{should:[{match:{title:ElasticSearch}},{match:{content:ElasticSearch}}],minimum_should_match:1}}],filter:[{term:{status:published}}]}}}含义是标题或正文至少一个字段命中ElasticSearch状态必须是published嵌套查询不要滥用但它是表达复杂业务语义的必要能力。十二、自然语言需求怎么翻译成 bool可以按下面方式转换“想要这个”放进must“不想要那个”放进must_not“只在某个范围里找”filter range“只要这些之一”结构化值用terms全文候选用should minimum_should_match“既要全文相关又要结构化限制”全文放must限制放filter例如“正文提到张三丰不要郭襄只查前 10 章”POSTarticle_search/_search{query:{bool:{must:[{match:{content:张三丰}}],filter:[{range:{chapter_index:{lte:10}}}],must_not:[{match:{content:郭襄}}]}}}十三、常见误区1. 所有条件都放 must这能跑但不一定合适。状态、分类、时间范围这类过滤条件不需要参与评分放filter更清楚。2. should 一定会限制结果不一定。当bool里已经有must或filter时should默认更多是加分条件不一定限制结果。如果希望它限制结果要明确设置minimum_should_match。3. bool 不是只能嵌一层复杂查询中bool可以嵌套。但不要为了炫技写得太深。优先让查询结构表达清楚业务含义。十四、一句话总结bool是 ElasticSearch 多条件查询的核心。最常用的判断方式是must必须匹配并参与评分filter必须匹配不参与评分must_not必须不匹配should最好匹配常用于加分业务搜索里match term range bool的组合非常常见。参考链接Boolean queryhttps://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-queryRange queryhttps://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-range-query