You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data ElasticsearchRepository使用@Query实现动态多条件查询咨询

报错原因

你当前的写法报错是因为Spring Data Elasticsearch处理@Query注解的参数时,会自动对传入的字符串做JSON转义处理,你传入的查询片段里的双引号都会被自动加上转义符,直接拼接会破坏原有查询语句的JSON结构,所以这种硬拼接部分查询片段的方案本身不可行。

可选实现方案

@Query不是唯一的可选方案,针对你这种字段不固定、需要动态追加查询条件的场景,更推荐以下实现方式:

方案1:使用NativeSearchQuery动态构建查询(最推荐)

直接通过ElasticsearchRestTemplate执行动态构建的查询,可以根据实际存在的字段任意追加match子句,适配性最高:

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

public class ActivityEsService {
    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    public List<Activity> findByDynamicConditions(String resource, Map<String, Object> additionalMatchConditions) {
        // 初始化bool查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 加入固定的_resource匹配条件
        boolQuery.must(QueryBuilders.matchQuery("_resource", resource));
        // 动态追加其他匹配条件
        additionalMatchConditions.forEach((field, value) -> {
            boolQuery.must(QueryBuilders.matchQuery(field, value));
        });
        // 构建查询对象
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .build();
        // 执行查询返回结果
        return elasticsearchRestTemplate.search(query, Activity.class)
                .stream().map(hit -> hit.getContent()).toList();
    }
}

调用示例:

// 需要追加的查询条件直接放入Map即可,支持任意数量、任意字段
Map<String, Object> addConditions = Map.of("_method", "GET", "_status", 200);
List<Activity> result = activityEsService.findByDynamicConditions("/test/api", addConditions);

方案2:使用Criteria API动态拼接(适合简单查询场景)

如果不想直接操作ES原生查询构建器,也可以用Spring Data Elasticsearch封装的Criteria API实现动态拼接:

import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;

public List<Activity> findByCriteriaConditions(String resource, Map<String, Object> additionalMatchConditions) {
    Criteria criteria = Criteria.where("_resource").is(resource);
    additionalMatchConditions.forEach((field, value) -> {
        criteria.and(Criteria.where(field).is(value));
    });
    CriteriaQuery query = new CriteriaQuery(criteria);
    return elasticsearchRestTemplate.search(query, Activity.class)
            .stream().map(hit -> hit.getContent()).toList();
}

方案3:强制使用@Query的实现方式

如果一定要用@Query注解实现,可以把完整的查询JSON作为参数传入,避免部分拼接产生的转义问题:

@Query("?0")
List<Activity> findByFullQuery(String fullQueryJson);

调用时自行拼接生成完整的合法bool查询JSON字符串即可,该方式需要自己保证JSON格式正确,灵活度低,不推荐使用。

总结

针对字段不固定的动态查询场景,优先选择动态构建NativeSearchQuery的方案,灵活度最高,也不会出现JSON转义异常问题。

内容的提问来源于stack exchange,提问作者Mauricio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 14:24:08