无法使用Mongoose更新Mongodb嵌套对象

0ejtzxu1  于 2023-06-30  发布在  Go
关注(0)|答案(1)|浏览(105)

我的架构:

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;

数据样本:

我的update函数,我希望更新数组中基于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();

执行更新函数后,数据没有更新。我能问问为什么吗?我哪里做错了?

qeeaahzv

qeeaahzv1#

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

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

但是arrayFilters[{ element: { name: 'children1', studentid: 13 }}],它将不匹配子文档。这就是为什么arrayFilters不工作。
您可以使用两个字段匹配子文档:element.nameelement.studentid,如果您不关心子文档的_id
或者使用整个子文档,如:

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

例如

import mongoose from 'mongoose';
import { config } from '../../config';

mongoose.set('debug', 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('Test', schema);

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

调试日志:

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

相关问题