无法使用Mongoose更新嵌套对象的MongoDB

huangapple go评论125阅读模式
英文:

Fail to update Mongodb nested object using Mongoose

问题

我的架构
```javascript
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;

数据示例:

无法使用Mongoose更新嵌套对象的MongoDB

我的更新函数,我希望根据 agestudentid 更新数组中整个对象:

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();

执行更新函数后,数据未更新。请问原因在哪里?我做错了什么吗?


<details>
<summary>英文:</summary>

My schema:
```javascript
import pkg from &quot;mongoose&quot;;

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(&quot;Test&quot;, schema) 

export default Test;

Data sample:

无法使用Mongoose更新嵌套对象的MongoDB

My update function, I wish to update the entire object inside the array base on age and studentid:

import { connectToDB } from &quot;./utils/database.js&quot;;
import Test from &quot;./models/test.js&quot;;

async function updateData() {
  await connectToDB();

  const res = Test.updateMany(
    {
      age: 34,
      name: &quot;name2&quot;,
    },
    {
      $set: {
        &quot;children.$[element]&quot;: {
          name: &quot;updatedname&quot;,
          studentid: 123456789,
        },
      },
    },
    {
      arrayFilters: [
        {
          element: {
            name: &quot;childr344en1&quot;,
            studentid: 137,
          },
        },
      ],
    },
    {upsert: true}
  );
  console.log(res)
}

await updateData();

After executing the update function, the data didn't update. May I ask why? Where am I doing wrong?

答案1

得分: 2

以下是翻译的内容:

由于child是嵌套在children字段中的subdocuments,子文档将具有一个_id字段。例如,子文档是

{ name: 'children1', studentid: 13, _id: ObjectId("649d778bc678b80c6073e487") }

arrayFilters[{ element: { name: 'children1', studentid: 13 }}],它不会匹配子文档。这就是为什么arrayFilters不起作用的原因。

如果您不关心子文档的_id,可以使用两个字段来匹配子文档:element.nameelement.studentid

或者像这样使用整个子文档:

{
  arrayFilters: [{ element: t2.children[0] }]
}
// t2.children[0] => { name: 'childr344en1', studentid: 137, _id: ObjectId("649d7aa53c3e28bda4c758e3") }

希望这对您有所帮助。

英文:

Since the child is subdocuments embedded in the children field. The subdocument will have a _id field. For example, the subdocument is

{ name: &#39;children1&#39;, studentid: 13, _id: ObjectId(&quot;649d778bc678b80c6073e487&quot;) }

But the arrayFilters is [{ element: { name: &#39;children1&#39;, studentid: 13 }}], it will not match the subdocument. That's why the arrayFilters does not work.

You can match the subdocument using two fields: element.name and element.studentid if you don't care about the _id of the subdocument.

Or use the entire subdocument like:

{
  arrayFilters: [{ element: t2.children[0] }]
}
// t2.children[0] =&gt; { name: &#39;childr344en1&#39;, studentid: 137, _id: ObjectId(&quot;649d7aa53c3e28bda4c758e3&quot;) }

E.g.

import mongoose from &#39;mongoose&#39;;
import { config } from &#39;../../config&#39;;

mongoose.set(&#39;debug&#39;, true);

const child = new mongoose.Schema({ name: String, studentid: Number });
const schema = new mongoose.Schema({ name: String, age: Number, children: [child] });

const Test = mongoose.model(&#39;Test&#39;, schema);

(async function main() {
	try {
		await mongoose.connect(config.MONGODB_URI);
		await Test.collection.drop();
		// seed
		const [, t2] = await Test.create([
			{ name: &#39;name1&#39;, age: 14, children: [{ name: &#39;children1&#39;, studentid: 13 }] },
			{
				name: &#39;name2&#39;,
				age: 34,
				children: [
					{ name: &#39;childr344en1&#39;, studentid: 137 },
					{ name: &#39;children2&#39;, studentid: 14 },
				],
			},
		]);
		const res = await Test.updateMany(
			{
				name: &#39;name2&#39;,
				age: 34,
			},
			{
				$set: {
					&#39;children.$[element]&#39;: {
						name: &#39;updatedname&#39;,
						studentid: 123456789,
					},
				},
			},
			{
				arrayFilters: [
					{
						&#39;element.name&#39;: &#39;childr344en1&#39;,
						&#39;element.studentid&#39;: 137,
					},
				],
				upsert: true,
			},
		);
		console.log(res);
		const r = await Test.findOne({ name: &#39;name2&#39;, age: 34 }).select({ __v: 0 });
		console.log(r?.toObject());
	} catch (error) {
		console.error(error);
	} finally {
		await mongoose.connection.close();
	}
})();

Debug logs:

Mongoose: tests.drop()
Mongoose: tests.insertOne({ name: &#39;name1&#39;, age: 14, children: [ { name: &#39;children1&#39;, studentid: 13, _id: ObjectId(&quot;649d795086edc01df88090ea&quot;) } ], _id: ObjectId(&quot;649d795086edc01df88090e9&quot;), __v: 0}, {})
Mongoose: tests.insertOne({ name: &#39;name2&#39;, age: 34, children: [ { name: &#39;childr344en1&#39;, studentid: 137, _id: ObjectId(&quot;649d795086edc01df88090ec&quot;) }, { name: &#39;children2&#39;, studentid: 14, _id: ObjectId(&quot;649d795086edc01df88090ed&quot;) } ], _id: ObjectId(&quot;649d795086edc01df88090eb&quot;), __v: 0}, {})
Mongoose: tests.updateMany({ name: &#39;name2&#39;, age: 34 }, { &#39;$setOnInsert&#39;: { __v: 0 }, &#39;$set&#39;: { &#39;children.$[element]&#39;: { name: &#39;updatedname&#39;, studentid: 123456789, _id: ObjectId(&quot;649d795186edc01df88090f0&quot;) } }}, { arrayFilters: [ { &#39;element.name&#39;: &#39;childr344en1&#39;, &#39;element.studentid&#39;: 137 } ], upsert: true})
{
  acknowledged: true,
  modifiedCount: 1,
  upsertedId: null,
  upsertedCount: 0,
  matchedCount: 1
}
Mongoose: tests.findOne({ name: &#39;name2&#39;, age: 34 }, { projection: { __v: 0 } })
{
  _id: new ObjectId(&quot;649d795086edc01df88090eb&quot;),
  name: &#39;name2&#39;,
  age: 34,
  children: [
    {
      name: &#39;updatedname&#39;,
      studentid: 123456789,
      _id: new ObjectId(&quot;649d795186edc01df88090f0&quot;)
    },
    {
      name: &#39;children2&#39;,
      studentid: 14,
      _id: new ObjectId(&quot;649d795086edc01df88090ed&quot;)
    }
  ]
}

huangapple
  • 本文由 发表于 2023年6月29日 17:13:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76579681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定