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

如何用MongoDB聚合合并基础记录与两层编辑数据并支持查询

MongoDB聚合实现基础数据与多角色编辑数据的合并查询

问题背景

我有一个存储基础图书记录的集合(示例数据如下),管理员和普通用户的编辑内容单独存在另一个集合中。需要编写MongoDB聚合操作,先合并基础数据与管理员编辑内容,再用用户编辑内容覆盖,同时保留编辑时新增的字段(比如示例中的frontOfStore),并且支持对这些新增字段进行查询。

基础记录集合(baseRecords)

[
  {
    "_id": "one",
    "name": "The Enchanted River",
    "description": "A mystical journey along a forgotten river that holds secrets of a lost civilization.",
    "paperCopy": true,
    "digitalCopy": true,
    "bestSeller": true,
    "isDiscounted": false,
    "discountPercentage": 0.0
  },
  {
    "_id": "two",
    "name": "Galactic Odyssey",
    "description": "An epic space adventure exploring distant galaxies and encountering alien civilizations.",
    "paperCopy": true,
    "digitalCopy": false,
    "bestSeller": true,
    "isDiscounted": false,
    "discountPercentage": 5.57
  },
  {
    "_id": "three",
    "name": "The Last Heir",
    "description": "A gripping tale of a young prince fighting to reclaim his throne against all odds.",
    "paperCopy": true,
    "digitalCopy": true,
    "bestSeller": true,
    "isDiscounted": false,
    "discountPercentage": 27.1
  },
  {
    "_id": "four",
    "name": "Quantum Dreams",
    "description": "A scientist's groundbreaking discovery challenges the very fabric of reality.",
    "paperCopy": true,
    "digitalCopy": true,
    "bestSeller": true,
    "isDiscounted": true,
    "discountPercentage": 22.85
  },
  {
    "_id": "five",
    "name": "The Forgotten Garden",
    "description": "An old gardener unravels the secrets of a mysterious estate with a tragic past.",
    "paperCopy": false,
    "digitalCopy": true,
    "bestSeller": false,
    "isDiscounted": false,
    "discountPercentage": 0.0
  }
]

编辑记录集合(edits)

[
  {
    "_id": "one",
    "user": "admin",
    "patch": {
      "bestSeller": false
    }
  },
  {
    "_id": "one",
    "user": "user1",
    "patch": {
      "bestSeller": true,
      "isDiscounted": true,
      "discountPercentage": 99,
      "frontOfStore": true
    }
  }
]

解决方案

聚合操作代码

db.baseRecords.aggregate([
  // 关联编辑集合,获取当前记录的所有编辑历史
  {
    $lookup: {
      from: "edits",
      localField: "_id",
      foreignField: "_id",
      as: "editHistory"
    }
  },
  // 筛选出管理员和目标用户的编辑内容(用户编辑优先级更高)
  {
    $addFields: {
      adminPatch: {
        $first: {
          $filter: {
            input: "$editHistory",
            cond: { $eq: ["$$this.user", "admin"] }
          }
        }
      },
      userPatch: {
        $first: {
          $filter: {
            input: "$editHistory",
            cond: { $eq: ["$$this.user", "user1"] } // 替换为当前查询的用户ID
          }
        }
      }
    }
  },
  // 按顺序合并数据:基础数据 → 管理员编辑覆盖 → 用户编辑覆盖
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          "$$ROOT",
          "$adminPatch.patch",
          "$userPatch.patch"
        ]
      }
    }
  },
  // 清理临时字段,让结果更整洁
  {
    $project: {
      editHistory: 0,
      adminPatch: 0,
      userPatch: 0
    }
  }
])

关键步骤说明

  1. 关联编辑数据:通过$lookup把基础记录和对应的编辑历史关联起来,方便后续处理。
  2. 拆分编辑角色:用$filter分别提取管理员和目标用户的编辑内容,确保同一字段下用户编辑会覆盖管理员的(因为后面合并时用户补丁在管理员补丁之后)。
  3. 合并与覆盖:$mergeObjects会按顺序合并对象,后面的对象字段会覆盖前面的同名字段,同时保留编辑时新增的字段(比如示例中的frontOfStore会直接加入最终结果)。
  4. 动态适配用户:把代码中的user1替换为当前登录用户的ID,就能实现针对不同用户展示其专属编辑后的内容。

新增字段查询示例

如果要查询frontOfStore为true的记录,只需在聚合末尾添加$match阶段:

{
  $match: {
    frontOfStore: true
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 11:06:21