Spring Data MongoDB中实现含MergeObjects的ReplaceRoot聚合管道方案
问题原因
你现有Java代码和原生查询效果不一致的核心原因有3点:
- 缺少原生查询中的
$addFields步骤,未将根文档的amount、createDate字段拼装为新对象追加到refunds数组末尾 replaceRoot逻辑错误,直接将refunds作为新根节点,没有合并原根文档的其他字段,导致根字段丢失- 缺少删除冗余
refunds字段的$unset步骤,且操作执行顺序和原生查询不匹配
正确实现代码
import org.springframework.data.mongodb.core.aggregation.*; import org.springframework.data.domain.Sort; import org.bson.Document; import java.util.Collections; // 1. 匹配条件,可根据业务需求自行调整criteria AggregationOperation match = Aggregation.match(criteria); // 2. 对应原生$addFields:将根文档的amount、createDate追加到refunds数组 AggregationOperation addFields = Aggregation.addFields() .addField("refunds") .withValue(ArrayOperators.ConcatArrays .arrayOf("refunds") .concat(Collections.singletonList( Document.parse("{\"amount\": \"$amount\", \"createDate\": \"$createDate\"}") )) .build(); // 3. 展开refunds数组 AggregationOperation unwind = Aggregation.unwind("refunds"); // 4. 对应原生replaceRoot+mergeObjects:合并原根字段和refunds字段作为新根 AggregationOperation replaceRoot = Aggregation.replaceRoot() .withDocument(Aggregation.mergeObjects() .and("$$ROOT") .and("refunds") .build()); // 5. 删除冗余的refunds字段 AggregationOperation unset = Aggregation.unset("refunds"); // 6. 按createDate倒序排序 AggregationOperation sort = Aggregation.sort(Sort.Direction.DESC, "createDate"); // 7. 限制返回条数,可按业务需求调整数值 AggregationOperation limit = Aggregation.limit(10); // 聚合操作顺序必须和原生查询一致 Aggregation aggregation = Aggregation.newAggregation( match, addFields, unwind, replaceRoot, unset, sort, limit ); // 执行查询 List<Payments> paymentRefunds = mongoTemplate.aggregate( aggregation, mongoTemplate.getCollectionName(Payments.class), Payments.class ).getMappedResults();
兼容说明
如果你使用的Spring Data MongoDB版本低于3.2,不支持链式构造mergeObjects,也可以直接传入原生语法构造replaceRoot,执行效果完全一致。
内容的提问来源于stack exchange,提问作者Patrick Teixeira
相关产品推荐
相关产品推荐

