mongoose - 带有$ set标志的findOneAndUpdate

Mis*_*r_L 4 mongoose mongodb node.js

考虑这个命令:

    WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, function(err) {
    ...
    })
Run Code Online (Sandbox Code Playgroud)

与此相对:

    WorkPlan.findOneAndUpdate({ _id: req.params.id }, { '$set': updateObj }, function(err) {
    ...
    })
Run Code Online (Sandbox Code Playgroud)

在开发我的项目时,我惊讶地发现第一个命令的结果与第二个命令的结果相同:它updateObj被合并到数据库中的现有记录中,即使在第一个命令应该是代替它.这是mongoose/mongodb中的错误还是我做错了什么?如何在更新时替换对象而不是合并它?我正在使用mongoose 4.0.7.

谢谢.

==========

更新:

这是实际的WorkPlan架构定义:

workPlanSchema = mongoose.Schema({
    planId: { type: String, required: true },
    projectName: { type: String, required: true },
    projectNumber: { type: String, required: false },
    projectManagerName: { type: String, required: true },
    clientPhoneNumber: { type: String, required: false },
    clientEmail: { type: String, required: true },
    projectEndShowDate: { type: Date, required: true },
    segmentationsToDisplay: { type: [String], required: false },
    areas: [
        {
          fatherArea: { type: mongoose.Schema.ObjectId, ref: 'Area' },
          childAreas: [{ childId : { type: mongoose.Schema.ObjectId, ref:   'Area' }, status: { type: String, default: 'none' } }]
        }
],
    logoPositions: [
                 {
                   lat: { type: Number, required: true },
                   lng: { type: Number, required: true }
                 }
    ],
    logoPath: { type: String, required: false },
    }, { collection: 'workPlans' });


WorkPlan = mongoose.model('WorkPlan', workPlanSchema);
Run Code Online (Sandbox Code Playgroud)

这是一个例子updateObj:

    var updateObj = {
        projectManagerName: projectManagerName,
        clientEmail: clientEmail,
        clientPhoneNumber: clientPhoneNumber,
        segmentationsToDisplay: segmentationsToDisplay ? segmentationsToDisplay.split(',') : []
    }
Run Code Online (Sandbox Code Playgroud)

因此,当我不使用$ set标志时,我会期望该字段projectNumber,例如,不存在于新记录中,但我发现它仍然存在.

axa*_*npi 9

Mongoose update将所有顶级密钥视为$set操作(在较旧的文档中更明确:Mongoose 2.7.x更新文档).

为了获得所需的行为,您需要将该overwrite选项设置为true:

WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, { overwrite: true }, function(err) {
    ...
})
Run Code Online (Sandbox Code Playgroud)

请参阅Mongoose Update文档