首页 > 解决方案 > 嵌套数组的猫鼬设置值

问题描述

我试图设置嵌套数组对象模式的值:

courses: [
    {
      days: [
        {
          courseDate: {
            type: String,
          },
          attendance: {
            type: Boolean,
          },
          reason: {
            type: String,
          },
        },
      ],
      courseId: {
        type: String,
      },
      name: {
        type: String,
      },
      startTime: {
        type: String,
      },
      endTime: {
        type: String,
      },
    },
  ],

这是我的尝试:

await Student.findOneAndUpdate(
      { "courses.days._id": "6117b0c45345db20f0dc3336" },
      { $set: { "courses.$.days.$.attendance": true } },
      { new: true }
    );

    await Student.findOneAndUpdate(
      { "courses.days._id": req.params.dayId },
      { "courses.$[courseIndex].days.$[dayIndex].attendance": true },
      {
        arrayFilters: [
          {
            courseIndex: req.params.courseId,
          },
          {
            dayIndex: req.params.dayId,
          },
        ],
      }
    );

这是文件:

 "courses" : [ 
        {
            "_id" : ObjectId("6117b0c45345db20f0dc3330"),
            "courseId" : "61155838b1fff211dd9a8765",
            "name" : "succ",
            "startTime" : "20:20",
            "endTime" : "23:20",
            "days" : [ 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3331"),
                    "courseDate" : "Wed Aug 04 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : false,
                    "reason" : ""
                }, 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3332"),
                    "courseDate" : "Wed Aug 11 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : false,
                    "reason" : ""
                }, 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3333"),
                    "courseDate" : "Wed Aug 18 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : false,
                    "reason" : ""
                }, 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3334"),
                    "courseDate" : "Wed Aug 25 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : false,
                    "reason" : ""
                }
            ]
        }, 
        {
            "_id" : ObjectId("6117b0c45345db20f0dc3335"),
            "courseId" : "61155838b1fff211dd9a8765",
            "name" : "test",
            "startTime" : "13:40",
            "endTime" : "15:40",
            "days" : [ 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3336"),
                    "courseDate" : "Thu Aug 05 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : false,
                    "reason" : ""
                }, 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3337"),
                    "courseDate" : "Thu Aug 12 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : false,
                    "reason" : ""
                }, 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3338"),
                    "courseDate" : "Thu Aug 19 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : true,
                    "reason" : ""
                }, 
                {
                    "_id" : ObjectId("6117b0c45345db20f0dc3339"),
                    "courseDate" : "Thu Aug 26 2021 00:00:00 GMT+0300 (Israel Daylight Time)",
                    "attendance" : false,
                    "reason" : ""
                }
            ]
        }
    ],

第一个是抛出一个错误:

Too many positional (i.e. '$') elements found in path 'courses.$.days.$.attendance'

第二个不起作用......我真的不明白第二种方法的问题在哪里。

它找到了正确的文档,但没有更新任何内容。

重要的是要注意每个数组的位置都是动态的,所以第二种方法也很好。

标签: node.jsmongodbmongoose

解决方案


过滤位置运算符 $[] 标识与更新操作的 arrayFilters 条件匹配的数组元素。

{ <update operator>: { "<array>.$[<identifier>]" : value } },
{ arrayFilters: [ { <identifier>: <condition> } ] }

如果 caseidentifier是一个对象,我们可以在 arrayFilters 条件中进一步查询该对象。

由于 arrayFilters 与 mongodb 相关,因此您需要在 mongoose 中使用 ObjectId 转换 id

    await Student.findOneAndUpdate(
      { 
        "courses": { "$elemMatch": { "_id": ObjectId(req.params.courseId)} }, 
        "courses.days": { "$elemMatch": { "_id": ObjectId(req.params.dayId)} } 
      },
      { "courses.$[courseIndex].days.$[dayIndex].attendance": true },
      {
        arrayFilters: [
          {
            courseIndex._id: ObjectId(req.params.courseId),
          },
          {
            dayIndex._id: ObjectId(req.params.dayId),
          },
        ],
        new: true,
      }
    );

编辑:
您需要使用new: true来获取更新的值


推荐阅读