如何在Node.js与Mongoose中更新单个嵌入式文档
在Node.js和Mongoose中更新单个嵌入式文档内容
首先假设我们有如下示例Schema,Parent模型包含一个children数组,数组元素是嵌入式文档:
const mongoose = require('mongoose'); const childSchema = new mongoose.Schema({ name: String, age: Number }); const parentSchema = new mongoose.Schema({ title: String, children: [childSchema] }); const Parent = mongoose.model('Parent', parentSchema);
下面是几种常见的更新场景及实现方式:
1. 通过嵌入式文档的_id更新(推荐)
利用MongoDB的位置操作符$,结合嵌入式文档的唯一_id定位目标,是最可靠的方式:
Parent.findOneAndUpdate( // 查询条件:匹配父文档ID,且子文档ID为目标ID { _id: parentId, 'children._id': childId }, // 更新操作:修改目标子文档的指定字段 { $set: { 'children.$.name': '新名字', 'children.$.age': 10 } }, // 选项:返回更新后的完整文档 { new: true } ) .then(updatedParent => console.log(updatedParent)) .catch(err => console.error(err));
2. 通过其他字段定位嵌入式文档
如果不知道子文档的_id,可以通过其他唯一字段(比如name)结合$elemMatch定位:
Parent.updateOne( { _id: parentId, children: { $elemMatch: { name: '旧名字' } } }, { $set: { 'children.$.age': 12 } }, { new: true } ) .then(result => console.log(result)) .catch(err => console.error(err));
3. 通过文档实例直接修改
如果已经获取了父文档实例,可以直接找到目标子文档修改后保存:
Parent.findById(parentId) .then(parent => { // 通过子文档ID查找目标 const targetChild = parent.children.id(childId); // 或者通过其他字段筛选: // const targetChild = parent.children.find(child => child.name === '旧名字'); if (!targetChild) throw new Error('未找到目标子文档'); // 修改字段 targetChild.name = '更新后的名字'; targetChild.age = 15; return parent.save(); }) .then(updatedParent => console.log(updatedParent)) .catch(err => console.error(err));
注意事项
- 位置操作符
$仅匹配第一个符合条件的子文档,如果需要更新多个匹配项,可使用MongoDB 3.6+支持的数组过滤操作符$[identifier]:// 更新所有age小于10的子文档的age为10 Parent.updateOne( { _id: parentId }, { $set: { 'children.$[elem].age': 10 } }, { arrayFilters: [{ 'elem.age': { $lt: 10 } }], new: true } ) .then(result => console.log(result)) .catch(err => console.error(err)); - 若不设置
new: true,Mongoose默认返回更新前的文档。
内容的提问来源于stack exchange,提问作者Saurabh Srivastav
相关产品推荐
相关产品推荐

