如何使用Mongoose,Express和Node更新MongoDB中的子文档?

问题描述 投票:0回答:2

所以我有一个Mongoose名为Profile的模型:

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const ProfileSchema = new Schema({
  user: {
    type: mongoose.Schema.ObjectId,
    ref: "user",
  },
  company: {
    type: String,
  },
  website: {
    type: String,
  },
  location: {
    type: String,
  },
  status: {
    type: String,
    required: true,
  },
  skills: {
    type: [String],
    required: true,
  },
  bio: {
    type: String,
  },
  githubusername: {
    type: String,
  },
  experience: [{
    title: {
      type: String,
      required: true,
    },
    company: {
      type: String,
      required: true,
    },
    location: {
      type: String,
    },
    from: {
      type: Date,
      required: true,
    },
    to: {
      type: Date,
    },
    current: {
      type: Boolean,
      default: false,
    },
    description: {
      type: String,
    },
  }, ],
  education: [{
    school: {
      type: String,
      required: true,
    },
    degree: {
      type: String,
      required: true,
    },
    fieldofstudy: {
      type: String,
      required: true,
    },
    from: {
      type: Date,
      required: true,
    },
    to: {
      type: Date,
    },
    current: {
      type: Boolean,
      default: false,
    },
    description: {
      type: String,
    },
  }, ],
  social: {
    youtube: {
      type: String,
    },
    twitter: {
      type: String,
    },
    facebook: {
      type: String,
    },
    linkedin: {
      type: String,
    },
    instagram: {
      type: String,
    },
  },
  date: {
    type: Date,
    default: Date.now,
  },
});

module.exports = Profile = mongoose.model("profile", ProfileSchema);

您可以看到我有一堆嵌套的子文档,并且我希望能够对其进行更新。特别是我希望能够使用experience端点更新PUT

这里是增加体验的终点:

router.put(
  "/experience", [
    auth, [
      check("title", "Title is required").not().isEmpty(),
      check("company", "Company is required").not().isEmpty(),
      check("from", "From date is required and needs to be from the past")
      .not()
      .isEmpty()
      .custom((value, {
        req
      }) => (req.body.to ? value < req.body.to : true)),
    ],
  ],
  async(req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({
        errors: errors.array()
      });
    }

    const {
      title,
      company,
      location,
      from,
      to,
      current,
      description,
    } = req.body;

    const newExp = {
      title,
      company,
      location,
      from,
      to,
      current,
      description,
    };

    try {
      const profile = await Profile.findOne({
        user: req.user.id
      });

      profile.experience.unshift(newExp);

      await profile.save();

      res.json(profile);
    } catch (err) {
      console.error(err.message);
      res.status(500).send("Server Error");
    }
  }
);

并且这可以将experience添加到该数组。但是,当我尝试更新时,这是我尝试过的不起作用的地方:

router.put("/experience/:exp_id", auth, async(req, res) => {
  try {
    const profile = await Profile.experience.findByIdAndUpdate(
      req.params._id, {
        $set: req.body,
      }, {
        new: true
      }
    );
    res.json(profile);
  } catch (error) {
    console.error(error);
    return res.status(500).json({
      msg: "Server error"
    });
  }
});

我收到此错误TypeError: Cannot read property 'findByIdAndUpdate' of undefined我在做什么错了?

这里是创建Profile时的一些Profile数据

{
  "social": {
    "youtube": "https://youtube.com/user/mojara2009",
    "twitter": null,
    "instagram": null,
    "linkedin": "https://linkedin.com/in/amen-ra",
    "facebook": null
  },
  "skills": [
    " HTML",
    " CSS",
    " JAVASCRIPT",
    " REACT",
    " REDUX",
    " JEST"
  ],
  "_id": "5eb1a19b83001bdb87e26492",
  "user": {
    "_id": "5eb10fecc3de3526caba5e50",
    "name": "Amen Ra",
    "avatar": "//www.gravatar.com/avatar/ee452fcb90a3913ca75ed4b4f06c4de6?s=200&r=pg&d=mm"
  },
  "__v": 19,
  "bio": "I am a Senior Full Stack Developer for Web App Company",
  "company": "Web App Company",
  "githubusername": "mojaray2k",
  "location": "Aventura, Fl",
  "status": "Developer",
  "website": "https://imaginationeverywhere.info",
  "date": "2020-05-05T22:33:41.596Z",
  "education": [{
      "current": false,
      "_id": "5eb2eccd659559371b2162f4",
      "school": "Bethune-Cookman University",
      "degree": "Bachelor of Arts",
      "fieldofstudy": "Mass Communication",
      "from": "1994-08-04T00:00:00.000Z",
      "to": "1999-04-26T00:00:00.000Z",
      "description": "Attended Bethune Cookman College in Daytona Beach, Fl"
    },
    {
      "current": false,
      "_id": "5eb2ecc2659559371b2162f3",
      "school": "Manual High School",
      "degree": "Diploma",
      "fieldofstudy": "NA",
      "from": "1990-09-01T00:00:00.000Z",
      "to": "1994-06-01T00:00:00.000Z",
      "description": "Attended High School my sophomore through senior year"
    },
    {
      "current": false,
      "_id": "5eb2ecb5659559371b2162f2",
      "school": "John F. Kennedy High School",
      "degree": "NA",
      "fieldofstudy": "NA",
      "from": "1989-09-01T00:00:00.000Z",
      "to": "1990-06-01T00:00:00.000Z",
      "description": "Attended High School my sophomore through senior year"
    },
    {
      "current": false,
      "_id": "5eb2ea28659559371b2162eb",
      "school": "Kunsmiller",
      "degree": "NA",
      "fieldofstudy": "Middle School",
      "from": "1988-02-01T05:00:00.000Z",
      "to": "1989-06-01T04:00:00.000Z",
      "description": "Attended Middle School There"
    }
  ],
  "experience": [{
      "current": false,
      "_id": "5eb356f74cc1ad499167567d",
      "title": "Senior Full Stack Engineer",
      "company": "Concept Solutions",
      "location": "Aventura, Fl",
      "from": "2016-01-03T00:00:00.000Z",
      "to": "2018-02-28T00:00:00.000Z",
      "description": "Worked as Full Stack Developer"
    },
    {
      "current": false,
      "_id": "5eb2de8fccd73b25fd1b2b39",
      "title": "Senior Full Stack Engineer",
      "company": "Jehovah Jireh, Inc",
      "location": "Aventura, Fl",
      "from": "2018-07-01T04:00:00.000Z",
      "to": "2019-07-01T04:00:00.000Z",
      "description": "Worked as Full Stack Developer"
    },
    {
      "current": true,
      "_id": "5eb203af1e004371b3284883",
      "title": "Senior Full Stack Engineer",
      "company": "Web App Company",
      "location": "Aventura, Fl",
      "from": "2019-07-01T04:00:00.000Z",
      "description": "Worked as Full Stack Developer"
    }
  ]
}
node.js mongodb express mongoose
2个回答
0
投票

无法将猫鼬模型架构作为Profile对象访问。相反,如果要更新模型的特定部分(在这种情况下为experience),则可以执行以下操作:

Profile.findByIdAndUpdate(
    { _id: req.params.exp_id}, 
    { $set: { experience: req.body} }, 
    { new: true }, your_callback);

我也相信是req.params.exp_id而不是req.params._id


0
投票

那是对猫鼬的正常响应,因为Profile是Collection Model Schema,而不是Profile object。另外,如果要更新阵列上的特定元素,则需要添加查询以帮助mongo查找仅在阵列上更新的数据。

这是在mongo上更新收集数据的备用查询。

    router.put("/experience/:exp_id", auth, async(req, res) => {
      try {
        const profile = await Profile.findOne(
          {
             _id: req.params.exp_id
          }
        );
        if (!profile) {
           throw new Error('No profile found.')
        }
        const index = profile.experience.findIndex((exp) => exp._id === req.body._id)
        profile.experience[index] = req.body
        profile.save
        res.json(profile);
      } catch (error) {
        console.error(error);
        return res.status(500).json({
          msg: "Server error"
        });
      }
    });
© www.soinside.com 2019 - 2024. All rights reserved.