【问题标题】:How can I update some fields of an embedded object using mongoose's findOneAndUpdate method and not lose the other fields?如何使用 mongoose 的 findOneAndUpdate 方法更新嵌入对象的某些字段而不丢失其他字段?
【发布时间】:2021-02-09 18:40:04
【问题描述】:
 router.put('/experience/update/:exp_id',
    auth,
    async (req, res) => {

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

        const newExp = {};
        newExp._id = req.params.exp_id;

        if (title) newExp.title = title;
        if (company) newExp.company = company;
        if (location) newExp.location = location;
        if (from) newExp.from = from;
        if (to) newExp.to = to;
        if (current) newExp.current = current;
        if (description) newExp.description = description;

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

            if (profile) {
                //UPDATE Experience
                profile = await Profile.findOneAndUpdate(
                    { user: req.user.id });
                const updateIndex = profile.experience.map(exp => exp._id).indexOf(req.params.exp_id);

                profile.experience[updateIndex] = newExp;
                    console.log('Experience updated!')
            }
            await profile.save();
            res.json(profile);

        } catch (error) {
            console.log(error.message);
            res.status(500).send('Internal Server Error');
        }


    }
)

我正在使用 findOneAndUpdate 方法来更新配置文件 mongoose 模型中的体验字段。 访问端点后,我输入了更新的详细信息,例如。公司和地点。但我失去了所有其他领域。那么如何只更新选定字段而其他字段保持不变呢?

以下是配置文件架构:

    const mongoose = require('mongoose');

const ProfileSchema = new mongoose.Schema({
    user: {
        type: mongoose.Schema.Types.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,
                required: true
            },
            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);

【问题讨论】:

  • 您丢失了哪些字段,您正在更新的个人资料字段或经验字段?
  • 我正在失去经验中的所有领域,除了我正在更新的领域
  • 我手动检查了经验是否具有价值。如果是,那就别管它了。我只是将 else 用于所有参数。如果有更好的方法请提出。
  • 我可以看到你的经验是一个数组 lke [exp1, exp2, exp3...],如果你像在代码中那样更新 exp2,整个对象将被替换为新对象,如果您想替换像公司一样的 exp 的某些部分,您必须像 profile.experience[updateIndex].company = newCompany; (我不使用猫鼬,而是使用原始 mongo,这就是 mongo 的工作方式)
  • 另外请查阅 mosgoose 的文档,它可能会告诉您更新数组中对象的某些字段的正确方法。但思路不变,更新对象将被完全替换,不会与现有对象合并。

标签: node.js mongodb express mongoose


【解决方案1】:

您的代码中存在一些问题。

  1. 您只向findOneAndUpdate 传递了一个参数。理想情况下,语法是findOneAndUpdate(filter, update)。所以基本上你需要将更新查询作为第二个参数传递。
profile = await Profile.findOneAndUpdate(
                    { user: req.user.id });
  1. 在下面的代码中,您正在修改配置文件对象并保存它。这不是必需的。这也是您丢失字段的原因。
 const updateIndex = profile.experience.map(exp => exp._id).indexOf(req.params.exp_id);

                profile.experience[updateIndex] = newExp;
                    console.log('Experience updated!')
            }
            await profile.save();

解决方案-

我们需要找出findOneAndUpdate(filter, update)update 部分。

这里是更新查询-

db.collection.update({
  "user": "5f96dc85ac5ae03160a024a8",
  "experience._id": "5f9826c3a3fa002ce0f11853"
},
{
  "$set": {
    "experience.$": {
      "current": false,
      "_id": "5f9826c3a3fa002ce0f11853",
      "title": "Senior developer",
      "company": "Morgan Stanley",
      "location": "Pune",
      "from": "2017-04-30T18:30:00.000Z",
      "to": "2020-07-08T18:30:00.000Z",
      "description": "testing"
    }
  }
})

试试here

尝试猫鼬方式:

const filter = { user: req.user.id, "experience._id": req.params.exp_id }
const update = { $set: { "experience.$": newExp } }
profile = await Profile.findOneAndUpdate(filter,update);

【讨论】:

  • 我可以为你写一个 mongo 查询。然后,您可以将其转换为 mongoose。请提供一份示例文件。
  • link 我已附上示例文档的驱动链接。
  • 也尝试添加猫鼬代码。你能给答案投票吗?
  • 解决方案有问题吗?您接受了答案并撤消了它?
猜你喜欢
  • 2019-09-27
  • 2016-09-13
  • 2021-04-12
  • 2016-12-15
  • 2022-11-01
  • 2017-07-03
  • 1970-01-01
  • 2016-03-23
  • 2022-11-27
相关资源
最近更新 更多