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

Node.js API中MongoDB文档数组对象的更新与新增实现

Node.js中MongoDB数组元素的更新/插入实现方案

需求说明

现有MongoDB文档如下:

{"_id": {"$oid": "64f832a51e7647d451ea8daa"},"requisitionOpenDate": "6/9/2023/ 13:34:37","requisitionId": 33280,"requestorName": "Amar","requestorEmail": "amaresh@pwc.com","projectSbu": "1","projectStage": "2","projectCompetency": "1","projectCodeCreated": "1","projectCode": 12345,"salesforceId": 12345,"resourceDetails": [{"rowid": "025820850bb6-7408257gh9","level": "Beginner","experience": 6,"location": "Maine","_id": "...."},{"rowid": "72504385254mm7-74238474hj4","level": "Advanced","experience": 7,"location": "Vienna","_id": "...."}],"__v": 0}

需要实现逻辑:

  • 若resourceDetails数组中存在指定rowid(来自MUI/x-data-grid,非MongoDB自带的_id)的对象,则将其更新为如下结构:
{"rowid": "025820850bb6-7408257gh9","level": "Rookie","experience": 6.3,"location": "Vancouver","_id": "...."}
  • 若不存在该rowid,则将该对象添加至resourceDetails数组中。

实现方案

方案一:使用Mongoose(ORM)实现

假设已定义对应Mongoose模型Requisition,可通过以下两种方式实现需求:

方式1:分两步执行更新/插入

const Requisition = require('./models/requisition');

async function upsertResource(requisitionId, targetResource) {
  // 第一步:尝试匹配rowid并更新数组元素
  const updateResult = await Requisition.updateOne(
    {
      requisitionId: requisitionId,
      'resourceDetails.rowid': targetResource.rowid
    },
    { $set: { 'resourceDetails.$': targetResource } }
  );

  // 若未匹配到任何元素,执行添加操作
  if (updateResult.matchedCount === 0) {
    await Requisition.updateOne(
      { requisitionId: requisitionId },
      { $push: { resourceDetails: targetResource } }
    );
  }
}

// 调用示例
const targetResource = {
  rowid: "025820850bb6-7408257gh9",
  level: "Rookie",
  experience: 6.3,
  location: "Vancouver",
  _id: "...." // 更新时保留原_id,新增时可省略由MongoDB自动生成
};
upsertResource(33280, targetResource);

方式2:使用bulkWrite批量操作(性能更优)

const Requisition = require('./models/requisition');

async function upsertResource(requisitionId, targetResource) {
  await Requisition.bulkWrite([
    // 先尝试更新匹配的数组元素
    {
      updateOne: {
        filter: {
          requisitionId: requisitionId,
          'resourceDetails.rowid': targetResource.rowid
        },
        update: { $set: { 'resourceDetails.$': targetResource } }
      }
    },
    // 若更新未匹配到,执行添加操作
    {
      updateOne: {
        filter: {
          requisitionId: requisitionId,
          'resourceDetails.rowid': { $ne: targetResource.rowid }
        },
        update: { $push: { resourceDetails: targetResource } }
      }
    }
  ]);
}

方案二:使用原生MongoDB驱动实现

若未使用ORM,直接通过原生驱动操作:

const { MongoClient } = require('mongodb');

async function upsertResource() {
  const uri = 'mongodb://localhost:27017'; // 替换为你的MongoDB连接地址
  const client = new MongoClient(uri);

  try {
    await client.connect();
    const db = client.db('your-database-name'); // 替换为你的数据库名
    const collection = db.collection('requisitions'); // 替换为你的集合名

    const requisitionId = 33280;
    const targetResource = {
      rowid: "025820850bb6-7408257gh9",
      level: "Rookie",
      experience: 6.3,
      location: "Vancouver",
      _id: "...."
    };

    // 尝试更新匹配的数组元素
    const updateResult = await collection.updateOne(
      {
        requisitionId: requisitionId,
        'resourceDetails.rowid': targetResource.rowid
      },
      { $set: { 'resourceDetails.$': targetResource } }
    );

    // 未匹配到则执行添加
    if (updateResult.matchedCount === 0) {
      await collection.updateOne(
        { requisitionId: requisitionId },
        { $push: { resourceDetails: targetResource } }
      );
    }
  } finally {
    await client.close();
  }
}

upsertResource();

注意事项

  • 新增元素时,_id字段可省略,MongoDB会自动生成唯一标识;更新时建议保留原数组元素的_id,避免破坏数据结构。
  • 示例中使用requisitionId作为文档匹配条件,你可根据业务需求替换为文档的_id或其他唯一标识。
  • 批量操作bulkWrite减少了数据库往返次数,在高并发场景下性能更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:53:10