You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用$cond将两段MongoDB用户更新查询合并为一个?

合并MongoDB数组更新与新增操作

原始代码逻辑

用户现有两段查询,逻辑如下:

  • 当override为true且userUpdate.user存在于users数组中时,更新该用户的role
  • 无论override是否为true,只要userUpdate.user不在users数组中,就将该用户对象添加到数组

原始代码:

if (override) {
    await ProjectModel.findOneAndUpdate(
        {
            _id: projectId,
            users: { $elemMatch: { user: userUpdate.user } }
        },
        {
            $set: {
                'users.$.role': userUpdate.role
            }
        }
    );
}

await ProjectModel.findOneAndUpdate(
    {
        _id: projectId,
        users: {
            $not: { $elemMatch: { user: userUpdate.user } }
        }
    },
    {
        $addToSet: { users: userUpdate }
    }
);

其中userUpdate是包含user(ObjectId类型)和role(字符串类型)的对象。

合并后的解决方案

可以利用MongoDB 4.2+支持的聚合管道更新,通过$cond条件判断实现逻辑合并,只需要一次findOneAndUpdate调用:

await ProjectModel.findOneAndUpdate(
    { _id: projectId },
    [
        {
            $set: {
                users: {
                    $cond: [
                        // 条件:用户已存在且override为true
                        {
                            $and: [
                                { $in: [userUpdate.user, '$users.user'] },
                                override
                            ]
                        },
                        // 满足条件时:更新对应用户的role
                        {
                            $map: {
                                input: '$users',
                                as: 'item',
                                in: {
                                    $cond: [
                                        { $eq: ['$$item.user', userUpdate.user] },
                                        { user: userUpdate.user, role: userUpdate.role },
                                        '$$item'
                                    ]
                                }
                            }
                        },
                        // 不满足条件时:判断是否需要新增用户
                        {
                            $cond: [
                                { $in: [userUpdate.user, '$users.user'] },
                                // 用户已存在但override为false,保留原数组
                                '$users',
                                // 用户不存在,添加新用户
                                { $concatArrays: ['$users', [userUpdate]] }
                            ]
                        }
                    ]
                }
            }
        }
    ],
    { new: true } // 可选:返回更新后的文档
);

逻辑说明

  1. 外层$cond判断:先检查目标用户是否存在且override为true
    • 满足时:用$map遍历users数组,匹配到目标用户就替换其role,其他用户保持不变
    • 不满足时:进入内层$cond判断
  2. 内层$cond判断:
    • 如果用户已存在但override为false,直接返回原users数组,不做修改
    • 如果用户不存在,用$concatArrays将新用户对象追加到数组末尾(效果等同于$addToSet,因为user是唯一的ObjectId)

注意事项

  • 该方案依赖MongoDB 4.2及以上版本,因为只有4.2+才支持在更新操作中使用聚合管道
  • 如果需要确保users数组中user的唯一性,$concatArrays和$addToSet效果一致(因为user是ObjectId,不会重复);如果业务场景可能出现重复的user值,建议替换为$addToSet以保证唯一性

内容的提问来源于stack exchange,提问作者Ankeeta Sahoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 05:07:07