Java中Elasticsearch使用类似MySQL的OR和AND查询

本文通过实例展示了如何使用SpringData Elasticsearch的ElasticsearchRestTemplate进行AND和OR的多条件查询。示例中,boolQuery用于构建复合查询,must对应AND,should对应OR。同时,讲解了如何在Java代码中构建这样的查询,并提供了匹配查询和术语查询的示例。

本文用实例来介绍如何使用Spring Data Elasticsearch的ElasticsearchRestTemplate来操作ES,在Java中Elasticsearch使用类似MySQL的OR和AND进行多条件查询。

官网

Elasticsearch Operations

bool query:

一种复合查询,把其余类型的查询包裹进来,支持以下三种逻辑关系。

must: AND   
must_not:NOT
should:OR

ES查询实例如下:

{
    "bool" : {
        "must" : { "term" : { "component" : "comp_1" } },  // must = And
        "should" : [                                       // should = Or
            { "term" : { "userId" : "A1A1" } },    
            { "term" : { "customerId" : "C1" } },
            { "term" : { "currentRole" : "ADMIN" }}
        ],
        "minimum_should_match" : 1
    }
}

在Java中代码示例:

@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;

org.elasticsearch.index.query.QueryBuilder qb = QueryBuilders
    .boolQuery()
    .must(termQuery("component", currentComponent))
    .should(termQuery("userId", currentUserId))
    .should(termQuery("customerId", currentCustomerId))
    .should(termQuery("currentRole", ADMIN))
    // .must(QueryBuilders.boolQuery().should(QueryBuilders.termsQuery("num", "6","8")))
    .minimumNumberShouldMatch(1);

该must部分是ANDS;

该should部分都或多或少ORS;

除了你可以指定的最小数量should(用s到比赛minimum_should_match),这个最低默认为1,我认为(但你可以将其设置为0,这意味着文件不匹配的should条件也将被返回)。

如果要进行涉及嵌套ANDs和ORs的更复杂的查询,只需将其他布尔查询嵌套在内部must或should部分中。

另外,当您寻找准确的值(id等)时,也许可以使用术语查询代替匹配查询,从而节省了分析阶段的时间(如果对这些字段进行了分析,则不一定有意义)对于ID)。如果对它们进行了分析,则您仍然可以这样做,但前提是您必须确切地知道术语的存储方式(例如,标准分析器将它们存储为小写)。

匹配关键字示例:

// es 查询满足条件1 或满足条件2 的结果合集
//主查询
matchQuery.must(
        QueryBuilders.boolQuery()
        .should(QueryBuilders.matchQuery("xm","好的"))//分词后匹配
            .should(QueryBuilders.matchParaseQuery("addr","钱江路"))//匹配完整词
            .should(QueryBuilders.termQuery("status",0))//完全匹配
            .should(QueryBuilders.termsQuery("keyword",string[]))//多关键字匹配
            );

    SearchResponse response = client.prepareSearch("indexName")
            .setFrom(0)
            .setSize(10)
            .setQuery(matchQuery)
            .get();

    SearchHits hits = response.getHits();
    int count = (int) hits.getTotalHits();

    for(SearchHit one:hits)
    {
        //遍历结果处理
    }

如果本篇文章对你有帮助的话,很高兴能够帮助上你。

当然,如果你觉得文章有什么让你觉得不合理、或者有更简单的实现方法又或者有理解不来的地方,希望你在看到之后能够在评论里指出来,我会在看到之后尽快的回复你。

你提的问题非常关键,而且理解得很准确! > ❓ **你的问题:** 能否实现类似MySQL 的这种逻辑: ```sql WHERE a = 1 AND (b = 1 OR c = 2) AND (d = 3 OR e = 4) ``` > ❌ **而当前写法的问题是:** ```java boolQuery.should(...); // b=1 or c=2 boolQuery.should(...); // d=3 or e=4 boolQuery.minimumShouldMatch(1); ``` 这样会导致整个 `should` 条件中 **只要满足一个子条件即可**(比如只匹配 `b=1` 就行),而不是“每一组 OR 都要满足”。 --- ## ✅ 正确答案:✅ 可以实现!但必须使用嵌套的 `BoolQueryBuilder` 你需要将每个 `(b=1 OR c=2)` 这样的逻辑封装成一个独立的 `BoolQueryBuilder`,然后把这个整体放入外层的 `must` 中。 --- ### ✅ 正确写法:使用嵌套 Bool 查询 ```java import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; public BoolQueryBuilder buildComplexQuery() { BoolQueryBuilder finalQuery = QueryBuilders.boolQuery(); // 1. a = 1 --> must finalQuery.must(QueryBuilders.termQuery("a", 1)); // 2. (b = 1 OR c = 2) --> 嵌套 bool query 放入 must BoolQueryBuilder group1 = QueryBuilders.boolQuery(); group1.should(QueryBuilders.termQuery("b", 1)); group1.should(QueryBuilders.termQuery("c", 2)); group1.minimumShouldMatch(1); // 至少满足 b=1 或 c=2 finalQuery.must(group1); // 3. (d = 3 OR e = 4) --> 另一个嵌套 bool query 放入 must BoolQueryBuilder group2 = QueryBuilders.boolQuery(); group2.should(QueryBuilders.termQuery("d", 3)); group2.should(QueryBuilders.termQuery("e", 4)); group2.minimumShouldMatch(1); // 至少满足 d=3 或 e=4 finalQuery.must(group2); return finalQuery; } ``` --- ### 🔍 生成的 ES DSL 类似于: ```json { "bool": { "must": [ { "term": { "a": 1 } }, { "bool": { "should": [ { "term": { "b": 1 } }, { "term": { "c": 2 } } ], "minimum_should_match": 1 } }, { "bool": { "should": [ { "term": { "d": 3 } }, { "term": { "e": 4 } } ], "minimum_should_match": 1 } } ] } } ``` 这完全等价于 SQL: ```sql WHERE a = 1 AND (b = 1 OR c = 2) AND (d = 3 OR e = 4) ``` --- ## 🚫 错误写法对比(你担心的是对的) ```java // ❌ 错误:所有 should 平铺在外层 boolQuery.should(QueryBuilders.termQuery("b", 1)); boolQuery.should(QueryBuilders.termQuery("c", 2)); boolQuery.should(QueryBuilders.termQuery("d", 3)); boolQuery.should(QueryBuilders.termQuery("e", 4)); boolQuery.must(QueryBuilders.termQuery("a", 1)); boolQuery.minimumShouldMatch(1); ``` 这个查询的意思是: > “只要 `b=1`, `c=2`, `d=3`, `e=4` 中任意一个成立”,就能通过。 而不是“每组都要满足一个”。 --- ## ✅ 应用到你的原始场景(imeiSn + 其他条件) 假设你要实现: ```sql WHERE status = 1 AND product_id = 1001 AND (product_sn = 'ABC' OR imei = 'ABC') AND (create_time BETWEEN start AND end OR type = 2) ``` ### Java 实现: ```java BoolQueryBuilder finalQuery = QueryBuilders.boolQuery(); // 1. a = 1 finalQuery.must(QueryBuilders.termQuery("status", 1)); finalQuery.must(QueryBuilders.termQuery("product_id", 1001)); // 2. (product_sn = ABC OR imei = ABC) BoolQueryBuilder snOrImei = QueryBuilders.boolQuery(); snOrImei.should(QueryBuilders.termQuery("product_sn.keyword", "ABC")); snOrImei.should(QueryBuilders.termQuery("imei.keyword", "ABC")); snOrImei.minimumShouldMatch(1); finalQuery.must(snOrImei); // 3. (create_time in range OR type = 2) BoolQueryBuilder timeOrType = QueryBuilders.boolQuery(); timeOrType.should(QueryBuilders.rangeQuery("create_time") .from(startTime).to(endTime)); timeOrType.should(QueryBuilders.termQuery("type", 2)); timeOrType.minimumShouldMatch(1); finalQuery.must(timeOrType); return finalQuery; ``` --- ## ✅ 总结:如何正确表达 `(A OR B) AND (C OR D)` | 目标 | 方法 | |------|------| | `A AND (B OR C)` | 外层 `must(A)`, 内层 `should(B,C)` + `must(内层)` | | `(A OR B) AND (C OR D)` | 两个嵌套 `boolQuery` 分别封装 OR,都加入 `must` | | `minimumShouldMatch(1)` | 必须加在 **每个嵌套的 boolQuery** 中 | | 性能优化 | 不影响评分的条件(如时间)可用 `filter` 替代 `must` | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值