mongodb 如何实现多表连改?

比如我现在有两个表,结构分别为:

// 表 A :
[{
    id: 1,
    name: 'aa'
}, {
    id: 2,
    name: 'bb'
}, {
    id: 3,
    name: 'cc'
}]
// 表 B :
[{
    user: '张三',
    array: [{ id: 1, name: 'aa' }, { id: 2, name: 'bb' }, { id: 3, name: 'cc' }]
}, {
    user: '李四',
    array: [{ id: 1, name: 'aa' }, { id: 2, name: 'bb' }, { id: 3, name: 'cc' }]
}, {
    user: '王五',
    array: [{ id: 1, name: 'aa' }, { id: 2, name: 'bb' }, { id: 3, name: 'cc' }]
}]

如果我现在操作修改 表A 中的数据,比如 id: 2 所在对象改为 { id: 2, name: 'dd' }

请问 mongo 是否可以在修改 表A 的同时修改 表B 中所有人物的 array 中的 id: 2 所在项

我现在能想到的就是笨办法就是改完 表A 之后嵌套遍历 表B,在通过匹配逐一修改,但我感觉这样做既没有效率也够笨重

还望指点,谢谢!

阅读 1.9k
2 个回答

你可以先用 $lookup 连接表 A 和表 B,然后使用 $map 和 $mergeObjects 更新表 B 中的数据:

db.B.aggregate([
  {
    $lookup: {
      from: 'A',
      let: { array: '$array' },
      pipeline: [
        {
          $match: {
            $expr: { $in: ['$_id', '$$array.id'] }
          }
        }
      ],
      as: 'A'
    }
  },
  {
    $addFields: {
      array: {
        $map: {
          input: '$array',
          as: 'item',
          in: {
            $mergeObjects: [
              '$$item',
              {
                $arrayElemAt: [
                  {
                    $filter: {
                      input: '$A',
                      as: 'a',
                      cond: { $eq: ['$$a._id', '$$item.id'] }
                    }
                  },
                  0
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      A: 0
    }
  },
  {
    $out: 'B'
  }
])

可以使用 MongoDB 的 $[] 操作符和 $ positional operator 实现在修改 表A 的同时修改 表B 中所有人物的 array 中对应数据项。

db.collection('tableA').updateOne(
    { id: 2 },
    { $set: { name: 'dd' } }
)
db.collection('tableB').updateMany(
    { 'array.id': 2 },
    { $set: { 'array.$.name': 'dd' } }
)

第一个命令会更新 表A 中id为2的元素,将其名称改为 "dd" 。
第二个命令使用了多重数组过滤器来筛选所有包含 id 为2的元素的 array 字段。接下来,使用 $ 及 . 符号来匹配嵌套元素,将其名称修改为 "dd" 。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题