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

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

Fail to update Mongodb nested object using Mongoose

问题

  1. 我的架构
  2. ```javascript
  3. import pkg from "mongoose";
  4. const { Schema, model, models } = pkg;
  5. const child = new Schema({ name: String, studentid: Number});
  6. const schema = new Schema({ name: String, age: Number, children: [child] });
  7. const Test = model("Test", schema)
  8. export default Test;

数据示例:

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

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

  1. import { connectToDB } from "./utils/database.js";
  2. import Test from "./models/test.js";
  3. async function updateData() {
  4. await connectToDB();
  5. const res = Test.updateMany(
  6. {
  7. age: 34,
  8. name: "name2",
  9. },
  10. {
  11. $set: {
  12. "children.$[element]": {
  13. name: "updatedname",
  14. studentid: 123456789,
  15. },
  16. },
  17. },
  18. {
  19. arrayFilters: [
  20. {
  21. element: {
  22. name: "childr344en1",
  23. studentid: 137,
  24. },
  25. },
  26. ],
  27. },
  28. {upsert: true}
  29. );
  30. console.log(res)
  31. }
  32. await updateData();

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

  1. <details>
  2. <summary>英文:</summary>
  3. My schema:
  4. ```javascript
  5. import pkg from &quot;mongoose&quot;;
  6. const { Schema, model, models } = pkg;
  7. const child = new Schema({ name: String, studentid: Number});
  8. const schema = new Schema({ name: String, age: Number, children: [child] });
  9. const Test = model(&quot;Test&quot;, schema)
  10. 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:

  1. import { connectToDB } from &quot;./utils/database.js&quot;;
  2. import Test from &quot;./models/test.js&quot;;
  3. async function updateData() {
  4. await connectToDB();
  5. const res = Test.updateMany(
  6. {
  7. age: 34,
  8. name: &quot;name2&quot;,
  9. },
  10. {
  11. $set: {
  12. &quot;children.$[element]&quot;: {
  13. name: &quot;updatedname&quot;,
  14. studentid: 123456789,
  15. },
  16. },
  17. },
  18. {
  19. arrayFilters: [
  20. {
  21. element: {
  22. name: &quot;childr344en1&quot;,
  23. studentid: 137,
  24. },
  25. },
  26. ],
  27. },
  28. {upsert: true}
  29. );
  30. console.log(res)
  31. }
  32. 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字段。例如,子文档是

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

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

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

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

  1. {
  2. arrayFilters: [{ element: t2.children[0] }]
  3. }
  4. // 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

  1. { 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:

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

E.g.

  1. import mongoose from &#39;mongoose&#39;;
  2. import { config } from &#39;../../config&#39;;
  3. mongoose.set(&#39;debug&#39;, true);
  4. const child = new mongoose.Schema({ name: String, studentid: Number });
  5. const schema = new mongoose.Schema({ name: String, age: Number, children: [child] });
  6. const Test = mongoose.model(&#39;Test&#39;, schema);
  7. (async function main() {
  8. try {
  9. await mongoose.connect(config.MONGODB_URI);
  10. await Test.collection.drop();
  11. // seed
  12. const [, t2] = await Test.create([
  13. { name: &#39;name1&#39;, age: 14, children: [{ name: &#39;children1&#39;, studentid: 13 }] },
  14. {
  15. name: &#39;name2&#39;,
  16. age: 34,
  17. children: [
  18. { name: &#39;childr344en1&#39;, studentid: 137 },
  19. { name: &#39;children2&#39;, studentid: 14 },
  20. ],
  21. },
  22. ]);
  23. const res = await Test.updateMany(
  24. {
  25. name: &#39;name2&#39;,
  26. age: 34,
  27. },
  28. {
  29. $set: {
  30. &#39;children.$[element]&#39;: {
  31. name: &#39;updatedname&#39;,
  32. studentid: 123456789,
  33. },
  34. },
  35. },
  36. {
  37. arrayFilters: [
  38. {
  39. &#39;element.name&#39;: &#39;childr344en1&#39;,
  40. &#39;element.studentid&#39;: 137,
  41. },
  42. ],
  43. upsert: true,
  44. },
  45. );
  46. console.log(res);
  47. const r = await Test.findOne({ name: &#39;name2&#39;, age: 34 }).select({ __v: 0 });
  48. console.log(r?.toObject());
  49. } catch (error) {
  50. console.error(error);
  51. } finally {
  52. await mongoose.connection.close();
  53. }
  54. })();

Debug logs:

  1. Mongoose: tests.drop()
  2. 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}, {})
  3. 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}, {})
  4. 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})
  5. {
  6. acknowledged: true,
  7. modifiedCount: 1,
  8. upsertedId: null,
  9. upsertedCount: 0,
  10. matchedCount: 1
  11. }
  12. Mongoose: tests.findOne({ name: &#39;name2&#39;, age: 34 }, { projection: { __v: 0 } })
  13. {
  14. _id: new ObjectId(&quot;649d795086edc01df88090eb&quot;),
  15. name: &#39;name2&#39;,
  16. age: 34,
  17. children: [
  18. {
  19. name: &#39;updatedname&#39;,
  20. studentid: 123456789,
  21. _id: new ObjectId(&quot;649d795186edc01df88090f0&quot;)
  22. },
  23. {
  24. name: &#39;children2&#39;,
  25. studentid: 14,
  26. _id: new ObjectId(&quot;649d795086edc01df88090ed&quot;)
  27. }
  28. ]
  29. }

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:

确定