Spring中使用mongoTemplate过滤数组元素时如何保留文档结构?
在Spring Boot中使用MongoTemplate过滤数组元素并保留原文档结构
需求场景
原始文档结构:
{ "A": "a", "B": "b", "C": [ { "name": "cat", "type": "animal" }, { "name": "john", "type": "human" } ] }
需要过滤出C数组中type为animal的元素,同时保留原文档结构,得到结果:
{ "A": "a", "B": "b", "C": [ { "name": "cat", "type": "animal" } ] }
解决方案:使用Aggregation聚合操作
通过MongoDB的$filter操作符结合Spring的Aggregation实现,既可以筛选数组元素,又能完整保留原文档的字段结构。
方法1:使用Spring Data的ArrayOperators.Filter
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; import org.springframework.data.mongodb.core.aggregation.ArrayOperators; import org.springframework.data.mongodb.core.query.Criteria; // 构建聚合阶段:保留A、B字段,过滤C数组 AggregationOperation projectStage = Aggregation.project("A", "B") .and(ArrayOperators.Filter.filter("C") .as("item") // 给数组元素设置别名 .by(Criteria.where("item.type").is("animal"))) // 筛选条件 .as("C"); // 将过滤后的数组重命名为原字段名C // 组装聚合管道 Aggregation aggregation = Aggregation.newAggregation(projectStage); // 执行查询,替换为你的实体类和集合名称 List<YourEntity> filteredDocs = mongoTemplate.aggregate( aggregation, "your_collection_name", YourEntity.class ).getMappedResults();
方法2:使用原生MongoDB表达式(更简洁)
如果熟悉MongoDB原生语法,可以直接用andExpression写过滤逻辑:
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; AggregationOperation projectStage = Aggregation.project("A", "B") .andExpression("filter(C, item => item.type == 'animal')") .as("C"); Aggregation aggregation = Aggregation.newAggregation(projectStage); List<YourEntity> filteredDocs = mongoTemplate.aggregate( aggregation, "your_collection_name", YourEntity.class ).getMappedResults();
注意事项
- 确保你的实体类
YourEntity结构与MongoDB文档匹配,其中C字段对应List<SubEntity>类型,SubEntity包含name和type属性。 - 如需多条件筛选,可修改筛选逻辑:比如
by(Criteria.where("item.type").is("animal").and("item.name").is("cat")),或者在andExpression中添加&&条件。
内容的提问来源于stack exchange,提问作者constant
相关产品推荐
相关产品推荐

