第二阶段 13 · bool 组合查询(AND / OR / NOT)

发布时间:2026/7/31 17:49:50
第二阶段 13 · bool 组合查询(AND / OR / NOT) 13 · bool 组合查询AND / OR / NOT阶段第二阶段 / 查询能力ES 查询boolmust / should / must_not / filter | PostgreSQL 对照AND/OR/NOT1. 概念bool是把多个查询条件组合起来的容器几乎所有复杂查询都靠它。它有 4 个子句bool 子句含义算分?SQL 对应must必须满足AND✅ 算分ANDfilter必须满足AND❌ 不算分、可缓存AND纯过滤should应该满足OR✅ 算分ORmust_not必须不满足NOT❌ 不算分NOT/!黄金法则需要相关性排序的条件放must只做过滤的条件放filter更快。2. PostgreSQL 对照SELECT*FROMsalesdataWHEREmaterialThinkPad-X1-- filter/mustANDnet_amount1000-- filterAND(geo_cdAPORgeo_cdNA)-- shouldANDstatusCANCELLED;-- must_not3. ES DSLGET salesdata_idx/_search { query: { bool: { filter: [ { term: { material: ThinkPad-X1 } }, { range: { net_amount: { gte: 1000 } } } ], should: [ { term: { geo_cd: AP } }, { term: { geo_cd: NA } } ], minimum_should_match: 1, must_not: [ { term: { status: CANCELLED } } ] } } }should单独用时minimum_should_match默认 1但当同时存在must/filter时should默认变为「可选加分项」想让它起「OR 过滤」作用务必显式写minimum_should_match: 1。4. Spring Boot 实现ComponentpublicclassDoc13BoolQuery{AutowiredprivateElasticsearchClientelasticsearchClient;publicListMapString,ObjectcomplexSearch(StringindexName,Stringmaterial,doubleminAmount,ListStringgeoCds,StringexcludeStatus)throwsIOException{SearchResponseMaprespelasticsearchClient.search(s-s.index(indexName).query(q-q.bool(b-{// ANDmaterial ?b.filter(f-f.term(t-t.field(material).value(material)));// ANDnet_amount ?b.filter(f-f.range(r-r.field(net_amount).gte(JsonData.of(minAmount))));// ORgeo_cd IN (...) —— 用 should minimum_should_matchfor(Stringgeo:geoCds){b.should(sh-sh.term(t-t.field(geo_cd).value(geo)));}b.minimumShouldMatch(1);// NOTstatus ?b.mustNot(mn-mn.term(t-t.field(status).value(excludeStatus)));returnb;})),Map.class);returnresp.hits().hits().stream().map(Hit::source).filter(Objects::nonNull).collect(Collectors.toList());}}这段就是本项目AbstractEsHepler#query的「进阶版」都用Query.of(q - q.bool(b - { ... return b; }))动态拼条件条件为空就跳过if。对照 MyBatis 的if动态 SQL 来理解最直观。5. 坑与最佳实践should的陷阱和must/filter同用时不写minimum_should_match会变成「可选加分」过滤不生效。想当 OR 用就显式写1。能用filter就别用must纯过滤放filter不算分、可缓存性能显著更好。must_not不算分它只排除不影响相关性。嵌套 bool复杂的(A OR B) AND (C OR D)用 bool 里再套 bool 实现。动态拼条件Java 里用if判空再b.filter(...)避免把空条件塞进去。下一篇14-exists-空值判断.md。