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
相关产品推荐
相关产品推荐

