如何获取MongoDB中指定任务关联的用户(Mongoose实现)
问题描述
我正在开发一个Web应用,使用MongoDB与Mongoose,此前因上手便捷选择该数据库,但当前部分场景似乎更适合关系型数据库。不过我希望先尝试用MongoDB解决问题,再考虑重构数据库代码。
我有三个集合:用户、待办任务(pending jobs)、已完成任务(completed jobs)。待办任务执行后需从集合删除,并创建已完成任务条目。用户模型通过Object ID引用列表字段关联这两个任务集合,我已掌握如何通过用户获取其所有待办和已完成任务:
const resp = await User.findOne({username:username}).populate(['pendingJobs', 'completedJobs'])
但我不清楚如何获取指定任务所属的用户?
补充模型代码
待办任务模型
const pendingJobModel = new mongoose.Schema({ date:{type:String, required: true, unique:true}, startTime:{type:String, required: true}, endTime:{type:String, required: true}, courseList:{type:[String], required: true}, member:{type:String}, clubUsername:{type:String, required: true}, clubPassword:{type:{token:String, iv:String}, required:true}, proxy:{type:Boolean, required: true, default:false}, active:{type:Boolean, required: true, default:false}, },{collection:'pendingjobs'}) module.exports = mongoose.model('PendingJob', pendingJobModel)
已完成任务模型
const completedJobModel = new mongoose.Schema({ date:{type:String, required: true, unique:true}, successful:{type:String, required: true}, time:{type:String}, course:{type:String}, member:{type:String}, },{collection:'completedjobs'}) module.exports = mongoose.model('CompletedJob', completedJobModel)
用户模型
const userModel = new mongoose.Schema({ username:{type:String, required: true, unique:true}, password:{type:String, required: true,}, refreshToken:{type:String, default: ''}, proxyConfig:{type: mongoose.Types.ObjectId, ref:'Proxy'}, pendingJobs:{type: [mongoose.Types.ObjectId], ref:'PendingJob'}, completedJobs:{type: [mongoose.Types.ObjectId], ref:'CompletedJob'} },{collection:'users'}) module.exports = mongoose.model('User', userModel)
解决方案
方法1:不修改现有模型,反向查询用户集合
当前只有用户集合存储了任务的引用,所以可以通过$in操作符在用户集合中查找包含指定任务ID的文档:
查询待办任务所属用户
// 假设已获取待办任务ID:pendingJobId const user = await User.findOne({ pendingJobs: pendingJobId });
查询已完成任务所属用户
// 假设已获取已完成任务ID:completedJobId const user = await User.findOne({ completedJobs: completedJobId });
注意:这种方式的缺点是用户集合数据量大时,查询效率会偏低,因为MongoDB需要遍历每个用户文档检查数组是否包含目标ID。
方法2:修改模型添加反向引用(推荐)
为了提升查询效率,建议在任务模型中添加指向用户的引用字段,直接通过任务文档关联用户:
修改待办任务模型
const pendingJobModel = new mongoose.Schema({ // 原有字段保留 date:{type:String, required: true, unique:true}, startTime:{type:String, required: true}, endTime:{type:String, required: true}, courseList:{type:[String], required: true}, member:{type:String}, clubUsername:{type:String, required: true}, clubPassword:{type:{token:String, iv:String}, required:true}, proxy:{type:Boolean, required: true, default:false}, active:{type:Boolean, required: true, default:false}, // 添加用户引用字段 user: { type: mongoose.Types.ObjectId, ref: 'User', required: true } },{collection:'pendingjobs'}) module.exports = mongoose.model('PendingJob', pendingJobModel)
修改已完成任务模型
const completedJobModel = new mongoose.Schema({ // 原有字段保留 date:{type:String, required: true, unique:true}, successful:{type:String, required: true}, time:{type:String}, course:{type:String}, member:{type:String}, // 添加用户引用字段 user: { type: mongoose.Types.ObjectId, ref: 'User', required: true } },{collection:'completedjobs'}) module.exports = mongoose.model('CompletedJob', completedJobModel)
同步更新逻辑
- 创建待办任务时,需同时将任务ID添加到用户的
pendingJobs数组,并在任务文档中存储用户ID; - 待办任务完成后,删除用户
pendingJobs中的该任务ID,添加到completedJobs数组,同时创建已完成任务时存储用户ID。
查询任务所属用户
现在可以直接通过populate关联用户:
查询待办任务所属用户
const pendingJob = await PendingJob.findById(pendingJobId).populate('user'); // pendingJob.user 即为所属用户
查询已完成任务所属用户
const completedJob = await CompletedJob.findById(completedJobId).populate('user'); // completedJob.user 即为所属用户
这种方式能利用MongoDB索引优化查询,数据量较大时效率更优。
内容的提问来源于stack exchange,提问作者Carter James
相关产品推荐
相关产品推荐

