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

MongoDB首次新增并更新对象内键的实现求助

MongoDB 文档数组新增/更新问题解决方案

问题分析

你的代码存在几个核心问题:

  • 查询条件里的users: { $elemMatch: { id: data.id2 } }会导致首次插入(文档和users数组均不存在)时匹配失败,upsert生成的文档不符合预期。
  • $inc: { 'users.point': ... }未指定数组内的具体目标元素,MongoDB无法定位到要更新的对象。
  • 同时使用$addToSet和$inc逻辑冲突,无法同时处理「新增数组元素」和「更新已有元素」的场景。

正确实现代码

要实现「首次创建文档并添加users元素,已有文档时更新对应user的point,无对应user则新增」的需求,可通过聚合管道更新结合upsert完成:

// 假设data结构为:{ id: '2022-08-06', id2: '345456', point: 1 }
client.db(dbProject).collection('test').updateOne(
  { '_id': data.id }, // 仅匹配文档_id,不提前过滤users数组
  [
    {
      $set: {
        users: {
          $cond: [
            { $in: [data.id2, '$users.id'] }, // 判断users中是否存在目标id
            // 存在则更新对应user的point
            {
              $map: {
                input: '$users',
                as: 'user',
                in: {
                  $mergeObjects: [
                    '$$user',
                    { point: { $add: ['$$user.point', data.point] } }
                  ]
                }
              }
            },
            // 不存在则新增user元素
            { $concatArrays: ['$users', [{ id: data.id2, point: data.point }]] }
          ]
        }
      }
    }
  ],
  {
    upsert: true,
    setDefaultsOnInsert: { users: [] } // 首次插入时初始化users为空数组
  }
);

代码说明

  1. 查询逻辑:仅通过_id匹配文档,避免因users数组不存在导致首次插入失败。
  2. 聚合管道判断:用$cond分支处理两种场景:
    • 存在目标user时,用$map遍历数组并更新对应元素的point值。
    • 不存在目标user时,用$concatArrays追加新的user对象。
  3. 初始化处理:setDefaultsOnInsert确保首次插入时users数组为空,避免$concatArrays报错。

如果仅需首次创建指定结构的文档,可简化为:

client.db(dbProject).collection('test').updateOne(
  { '_id': '2022-08-06' },
  { $set: { users: [{ id: '345456', point: 1 }] } },
  { upsert: true }
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 12:45:35