使用Mongoose更新MongoDB嵌套对象失败,求排查原因
问题背景
我的Mongoose Schema定义如下:
import pkg from "mongoose"; const { Schema, model, models } = pkg; const child = new Schema({ name: String, studentid: Number}); const schema = new Schema({ name: String, age: Number, children: [child] }); const Test = model("Test", schema) export default Test;
数据示例:
我希望根据age和studentid更新数组中的整个对象,编写了如下更新函数:
import { connectToDB } from "./utils/database.js"; import Test from "./models/test.js"; async function updateData() { await connectToDB(); const res = Test.updateMany( { age: 34, name: "name2", }, { $set: { "children.$[element]": { name: "updatedname", studentid: 123456789, }, }, }, { arrayFilters: [ { element: { name: "childr344en1", studentid: 137, }, }, ], }, {upsert: true} ); console.log(res) } await updateData();
执行该更新函数后,数据并未发生更新,请问这是什么原因?我哪里出错了?
问题原因及修复方案
你的更新代码存在两个关键问题:
1. Array Filters 语法错误
你在arrayFilters里用了element: {name: "childr344en1", studentid: 137}的写法,这是错误的。正确写法应该直接指定数组元素的字段匹配条件,element是你在更新路径中定义的占位符,需要通过它匹配数组元素的具体字段:
arrayFilters: [ { "element.name": "childr344en1", "element.studentid": 137 } ]
这种写法才能让MongoDB找到children数组中同时满足name和studentid条件的元素。
2. 更新选项参数拆分错误
updateMany方法的第三个参数是合并的选项对象,你把arrayFilters和upsert拆成两个独立对象传入,会导致upsert被识别为第四个参数(回调函数),无法生效,同时MongoDB也无法正确解析选项。正确做法是将两个选项合并到同一个对象:
{ arrayFilters: [ { "element.name": "childr344en1", "element.studentid": 137 } ], upsert: true }
修复后的完整代码
import { connectToDB } from "./utils/database.js"; import Test from "./models/test.js"; async function updateData() { await connectToDB(); const res = Test.updateMany( { age: 34, name: "name2", }, { $set: { "children.$[element]": { name: "updatedname", studentid: 123456789, }, }, }, { arrayFilters: [ { "element.name": "childr344en1", "element.studentid": 137 } ], upsert: true } ); console.log(res) } await updateData();
另外,建议先确认查询条件age:34和name:"name2"确实能匹配到数据库中的文档,这也是更新不生效的常见原因之一。
内容的提问来源于stack exchange,提问作者TungTung
相关产品推荐
相关产品推荐

