如何在Mongo集合中用排序后的数组更新Refs数组?
解决ShowsList数组排序并更新的问题
你当前的问题核心是:populate操作是Mongoose在内存中将ObjectId替换为对应的Show文档,内存中排序后的是Show对象数组,而非数据库存储的ObjectId数组,所以直接save()不会修改数据库里的原始数组。要解决这个问题,需要提取排序后的Show的ObjectId,再替换数据库中的数组。
方法一:应用层处理(简单直观)
先通过populate获取排序后的Show对象,提取它们的_id组成新数组,再更新数据库:
const userId = req.body.user._id; // 1. 查询并填充排序后的Show列表 const showsListPopulatedSorted = await ShowsList.findOne( { showsListOwner: userId } ).populate({ path: 'shows', options: { sort: { 'showName': 1 } } }); // 2. 提取排序后的Show的ObjectId数组 const sortedShowIds = showsListPopulatedSorted.shows.map(show => show._id); // 3. 更新数据库中的shows数组 await ShowsList.findOneAndUpdate( { showsListOwner: userId }, { $set: { shows: sortedShowIds } } );
方法二:数据库层面聚合(效率更高)
如果节目数量较多,推荐用MongoDB聚合管道直接在数据库完成排序和ID收集,避免把大量数据拉到应用层:
const mongoose = require('mongoose'); const userId = req.body.user._id; // 1. 通过聚合获取排序后的Show ObjectId数组 const sortedResult = await ShowsList.aggregate([ // 匹配目标用户的ShowsList { $match: { showsListOwner: mongoose.Types.ObjectId(userId) } }, // 拆分shows数组 { $unwind: '$shows' }, // 关联Show集合获取showName { $lookup: { from: 'shows', // 注意这里是Show模型对应的集合名(默认是复数) localField: 'shows', foreignField: '_id', as: 'showDetail' } }, { $unwind: '$showDetail' }, // 按showName升序排序 { $sort: { 'showDetail.showName': 1 } }, // 重新组合成排序后的ObjectId数组 { $group: { _id: '$_id', sortedShows: { $push: '$shows' } } } ]); // 2. 更新数据库 if (sortedResult.length > 0) { await ShowsList.findByIdAndUpdate( sortedResult[0]._id, { $set: { shows: sortedResult[0].sortedShows } } ); }
关键说明
- 为什么
save()无效?:populate后的shows字段是内存中的Show对象,而数据库存储的是ObjectId数组,Mongoose不会自动将填充后的对象转换为排序后的ObjectId数组进行持久化。 - 清空数组的正确方式:如果需要清空
shows数组,应该用$set: { shows: [] },而非deleteMany(deleteMany是用于删除集合文档的方法,不适用于数组元素)。
内容的提问来源于stack exchange,提问作者SwineBurglar
相关产品推荐
相关产品推荐

