MongoDB如何将嵌套数组拆分为多个独立文档并支持排序分页?
MongoDB 数组拉平查询实现方案
一、核心实现思路
要实现数组拆分、字段提升的需求,直接使用MongoDB聚合管道即可完成,共包含4个核心阶段:
- 匹配阶段(可选):用Criteria定义过滤条件,筛选符合要求的原始文档
- 拆分阶段:使用
$unwind拆解adress数组,每个数组元素对应一条独立文档 - 字段映射阶段:将
adress数组内的字段提升到顶级,同时保留所有原有顶级字段、删除冗余的adress字段 - 排序&分页阶段:按
createDate排序后限制返回条数,适配API响应需求
二、原生MongoDB聚合查询示例
db.your_collection_name.aggregate([ // 可选:有过滤需求时添加match阶段 { $match: { // 此处可填写自定义过滤条件,比如 status: "SINGLE" } }, // 拆分adress数组 { $unwind: "$adress" }, // 字段映射,拉平层级 { $project: { _id: 0, // 不需要返回_id时设为0即可 type: 1, code: 1, Name: 1, currency: 1, status: 1, localization: "$adress.localization", createDate: "$adress.createDate" } }, // 按createDate排序,1为升序,-1为降序 { $sort: { createDate: -1 } }, // 限制返回条数,根据API需求修改数值 { $limit: 10 } ])
三、Spring Data MongoDB(Criteria+Aggregation)实现代码
项目中使用Spring Data MongoDB的场景下,可直接通过Aggregation配合Criteria实现需求:
import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.query.Criteria; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; // 自定义的结果接收类,需和最终返回字段结构对应 import com.yourpackage.vo.AddressResultVO; public List<AddressResultVO> queryAddressList(int limitSize) { // 1. 构造查询条件(无过滤需求可省略match阶段) Criteria criteria = Criteria.where("status").is("SINGLE") // 可继续追加其他自定义过滤条件 .and("type").is("PF"); // 2. 构造聚合管道 Aggregation aggregation = newAggregation( match(criteria), // 条件匹配,无过滤需求可删除该行 unwind("adress"), // 拆分adress数组 project("type", "code", "Name", "currency", "status") .and("adress.localization").as("localization") .and("adress.createDate").as("createDate") .andExclude("_id"), // 不需要返回_id时保留该行,否则删除 sort(Sort.Direction.DESC, "createDate"), // 按createDate倒序,可调整排序方向 limit(limitSize) // 限制返回条数 ); // 3. 执行查询,第二个参数为原始集合名称,第三个参数为结果接收类 AggregationResults<AddressResultVO> results = mongoTemplate.aggregate(aggregation, "your_collection_name", AddressResultVO.class); return results.getMappedResults(); }
注意:
AddressResultVO需要包含type、code、Name、currency、status、localization、createDate对应属性以及getter/setter方法。
内容的提问来源于stack exchange,提问作者Patrick Teixeira
相关产品推荐
相关产品推荐

