简体   繁体   中英

Updating a subdocument in array in Mongoose

I have two models, defined in two seperate files

//models/Projects.js
const mongoose = require('mongoose');

export const projectSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true,
        trim: true,
    },
    companyBackground: {
        type: String,
        required: false,
        trim: true,
    }
});
module.exports = mongoose.models.Project || mongoose.model('Project', projectSchema);
//models/User.js
const mongoose = require('mongoose');
const { projectSchema } = require('./Project');

const userSchema = new mongoose.Schema({
    projects: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Project' }]
});

module.exports = mongoose.models.User || mongoose.model('User', userSchema);

I create a new user, and then create a new project, by pushing it to the user

import dbConnect from "utils/dbConnect";
import User from "models/User";
import Project from "models/Project";

export default async (req, res) => {
    await dbConnect();
    const { query: { id }, method } = req;

    switch (method) {
        case "POST":
            try {
                    const user = await User.findById(id);

                    if (!user) {
                        return res.status(400).json({ success: false, message: "User not found" });
                    }

                    const newProject = new Project(req.body);
                    console.log(newProject);
                    user.projects.push(newProject);
                    await user.save();

                    if (!user) {
                        return res.status(400).json({ success: false, message: "Project not added" 
                    }
                    res.status(200).json({ data: user });

            } catch (error) {
                res.status(400).json({ success: false, message: error.message });
            }
            break;
        default:
            res.status(400).json({ success: false });
            break;
    }
};

Bu here is the question. I can easily create a new project and save it to the user, but not make any updates. Approaches I have tried include (but are not limited to):

To demonstrate the problems, see

const updateString = "projects.$." + req.body.property;
    Project.findOneAndUpdate(
        { _id: req.body.projectid },
            { $set: { [updateString]: req.body.value } },
                function (error, success) {
                    if (error) {
                        console.log('error');
                        console.log(error);
                    } else {
                        console.log("success");
                        console.log(success);  //Returns null
                    }
                }
    );

The above returns null

And when I do this, I get

User.findById(userid)
    .then((user => {
        const project = user.projects.id(req.body.projectid); //user.projects.id is not a function
        project.set(newContent);
        return user.save();
        }))
        .then((user) => {
            res.send(user);
        })
            .catch((error) => {
                console.log('error: ', error.message);
                res.status(400).json({ success: false, message: error.message });
    });

Here is says that user.projects.id is not a function... In mongo DB Atlas, I can see that the project has indeed been created.

This is turning me crazy, can someone tell me what I am doing wrong? Would it be better, simply to create the projects as arrays (without making them as a mongoose object?)

When pushing to user.projects you should just add the _id since the property is defined as ObjectId[] :

try {
  const user = await User.findById(id);

  if (!user) {
    return res.status(400).json({ success: false, message: 'User not found' });
  }

  const newProject = await Project.create(req.body);
  console.log(newProject);
  user.projects.push(newProject._id);
  await user.save();

  if (!user) {
    return res
      .status(400)
      .json({ success: false, message: 'Project not added' });
  }
  res.status(200).json({ data: user });
} catch (error) {
  res.status(400).json({ success: false, message: error.message });
}

Then, to update a Project you can simply do:

    Project.findByIdAndUpdate(
        req.body.projectid,
        { $set: { [req.body.property]: req.body.value } },
        { new: true }, // returns updated doc
        function (error, success) {
            if (error) {
                console.log('error');
                console.log(error);
            } else {
                console.log("success");
                console.log(success);  //Returns null
            }
        }
    );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM