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

Spring Data MongoDB中如何向@Query注解传递数组?

Spring Boot MongoDB 自定义$or查询报错解决

问题场景

需要在Spring Boot中结合MongoDB编写自定义查询,向$or操作符传递数组条件。

MongoDB目标查询语句:

{
  "title": {"$regex":"Ab","$options":"i"},
  "$or": [{"genre": "Romance"}, {"genre": "Music"}],
  "release_date": {"$gte": "2000", "$lte": "2020"}
}

编写的Spring Boot Repository代码:

@Query("{title: { '$regex':?0,'$options':'i' }, $or: ?1, release_date: { $gte: ?2, $lte: ?3 }}")
List<Movie> findAllByFilters(String title, String[] genres, String min_date, String max_date);

执行后抛出错误:

Query failed with error code 2 with name 'BadValue' and error message '$or/$and/$nor entries need to be full objects'

错误原因

MongoDB的$or操作符要求每个元素都是完整的查询对象(比如{genre: 'Romance'}),但直接传递字符串数组["Romance", "Music"]时,Spring Data MongoDB会把它原样传入查询,导致$or的元素是字符串而非对象,触发解析错误。

解决方案

方案1:使用SpEL表达式在@Query中转换数组

直接在@Query注解里通过SpEL表达式,将传入的字符串数组转换为$or需要的对象数组:

@Query("{title: { '$regex':?0,'$options':'i' }, " +
        "$or: ?1.![{genre: #this}], " +
        "release_date: { $gte: ?2, $lte: ?3 }}")
List<Movie> findAllByFilters(String title, String[] genres, String min_date, String max_date);

这里?1.![{genre: #this}]的作用是:遍历参数?1(即genres数组),将每个元素#this包装为{genre: 元素值}的对象,最终生成符合$or要求的对象数组。

方案2:手动构造$or条件对象列表

在Service层将字符串数组转换为包含查询条件的对象列表,再传入Repository:

  1. 修改Repository方法的参数类型:
@Query("{title: { '$regex':?0,'$options':'i' }, $or: ?1, release_date: { $gte: ?2, $lte: ?3 }}")
List<Movie> findAllByFilters(String title, List<Document> orConditions, String min_date, String max_date);
  1. Service层处理参数:
import org.bson.Document;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

// 调用示例
String[] genres = {"Romance", "Music"};
List<Document> orConditions = Arrays.stream(genres)
    .map(genre -> new Document("genre", genre))
    .collect(Collectors.toList());
List<Movie> movies = movieRepository.findAllByFilters("Ab", orConditions, "2000", "2020");

方案3:使用MongoTemplate动态构建查询

如果需要更灵活的查询逻辑,推荐使用MongoTemplate直接构建查询:

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

// 注入MongoTemplate
private final MongoTemplate mongoTemplate;

public List<Movie> findMoviesByFilters(String title, String[] genres, String minDate, String maxDate) {
    Query query = new Query();
    // 标题模糊匹配
    query.addCriteria(Criteria.where("title").regex(title, "i"));
    // 构造$or条件
    List<Criteria> orCriterias = Arrays.stream(genres)
        .map(genre -> Criteria.where("genre").is(genre))
        .collect(Collectors.toList());
    query.addCriteria(new Criteria().orOperator(orCriterias.toArray(new Criteria[0])));
    // 日期范围过滤
    query.addCriteria(Criteria.where("release_date").gte(minDate).lte(maxDate));
    
    return mongoTemplate.find(query, Movie.class);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:43:22