mongoose - 使用$set标志的findOneAndUpdate

10

考虑以下命令:

    WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, function(err) {
    ...
    })

与此相比:

    WorkPlan.findOneAndUpdate({ _id: req.params.id }, { '$set': updateObj }, function(err) {
    ...
    })

在开发我的项目时,我惊讶地发现第一个命令的结果与第二个命令的结果相同:即使在第一种情况下,updateObj 应该替换现有记录,它也会合并到数据库中的现有记录中。这是 mongoose/mongodb 的 bug 还是我的操作有误?我如何在更新时替换对象而不是将其合并?我使用的是 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);

这是updateObj的一个示例:

    var updateObj = {
        projectManagerName: projectManagerName,
        clientEmail: clientEmail,
        clientPhoneNumber: clientPhoneNumber,
        segmentationsToDisplay: segmentationsToDisplay ? segmentationsToDisplay.split(',') : []
    }

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

17

Mongoose的更新操作将所有顶层键看作$set操作(在旧文档中更清楚地说明: Mongoose 2.7.x 更新文档)。

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

WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, { overwrite: true }, function(err) {
    ...
})

请参考Mongoose更新文档


谢谢提供这个信息,我之前不知道。 - Mister_L

0
除了上面的答案之外:

[options.overwrite=false] «布尔值» 默认情况下,如果您在doc中不包含任何更新操作符,Mongoose将为您包装doc中的$set。这可以防止您意外覆盖文档。此选项告诉Mongoose跳过添加$set。

文档链接:https://mongoosejs.com/docs/api.html#model_Model.update

0

这对我来说是有效的,在Mongoose 5.10.1中使用$set

 WorkPlan.where({ _id: req.params.id }).updateOne(updateObj);

注意:如果您有内部对象,则请在 updateObj 中给出每个键的准确路径。
例如:

"Document.data.age" = 19

参考:https://mongoosejs.com/docs/api.html#query_Query-set

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接