如何在Mongoose中更新用户角色数组并避免重复值
给用户批量添加角色时避免重复条目
问题场景
现有两个MongoDB集合:
- Roles:存储角色信息
- Users:存储用户信息,其中
roles字段是引用Roles集合的ObjectId数组
当前代码使用$push批量给用户添加角色时,会出现重复添加同一角色的问题(比如同一个管理员角色被多次加入用户的roles数组),相关代码及问题截图如下:
User Schema
const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ id: { type: String }, username: { type: String, required: true, unique: true }, phone: { type: String, required: false, unique:true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, roles: [ { type: mongoose.Schema.Types.ObjectId, required: true, ref:'Role' } ], otp: { required: false, type:String } }); module.exports = mongoose.model('User', userSchema);
原问题代码
const rolesArr = get(validated, 'value.roles'); // ['super-administrator', 'administrator'] const usernameArr = get(validated, 'value.users'); // ['user-1', 'user-2'] const roles = await Role.find({slug:{$in:rolesArr}}); // 匹配角色slug的Roles集合数组 const set = { $push: { // 向现有数组中推送元素 roles: roles } } const users = await User.updateMany({username: {$in: usernameArr}}, set);
问题截图

解决方案
核心是使用MongoDB的$addToSet操作符替代$push,$addToSet会自动忽略数组中已存在的元素;配合$each可以实现批量添加多个元素。
修改后的代码
const rolesArr = get(validated, 'value.roles'); // ['super-administrator', 'administrator'] const usernameArr = get(validated, 'value.users'); // ['user-1', 'user-2'] // 查询目标角色并提取ObjectId数组 const roles = await Role.find({ slug: { $in: rolesArr } }); const roleIds = roles.map(role => role._id); // 使用$addToSet + $each实现去重批量添加 const updateOptions = { $addToSet: { roles: { $each: roleIds } } } const users = await User.updateMany({ username: { $in: usernameArr } }, updateOptions);
代码说明
- 提取角色ID:将查询到的Role对象转换为ObjectId数组,确保存入users.roles的是正确的引用类型
- $addToSet + $each:
$addToSet:仅当元素不存在于数组中时才添加$each:允许批量传入多个元素,否则$addToSet会把整个数组当成单个元素插入
这样就能保证每个用户的roles数组中不会出现重复的角色条目。
内容的提问来源于stack exchange,提问作者Alaksandar Jesus Gene
相关产品推荐
相关产品推荐

