【问题标题】:Default value not set while using Update with Upsert as true使用带有 Upsert 的更新为 true 时未设置默认值
【发布时间】:2015-01-08 00:42:09
【问题描述】:

我有以下模型供用户使用:

var UserSchema = new mongoose.Schema({

    name: String,
    dob: Date,
    sex: String,
    photo: String,
    email: {type: String, index: {unique: true, required: true}},
    created: {type: Date, default: Date.now}
});

var User = mongoose.model('Users', UserSchema);

如您所见,“created”字段采用当前日期的默认值,以便在创建新用户时自动设置。

我在发布用户详细信息时使用以下查询:

User.findOneAndUpdate({email: user.email}, user, {upsert: true}, function (err, user) {
            if (err) {
                return callback (err);
            } else {
                callback(null, user);
            }
        });

findOneAndUpdateupsert: true 一起使用的目的是返回现有配置文件或创建新配置文件。它还会根据发布的数据更新任何字段。

但是,created 字段每次都会更新为当前日期,即使未发布创建的字段。如何确保该字段只设置一​​次?

编辑

数据库中的示例对象:

{
    "_id" : ObjectId("54620b38b431d48bce7cab81"),
    "email" : "someone@google.com",
    "__v" : 0,
    "name" : "somone",
    "sex" : "male"
}

事实证明,即使在使用 upsert 创建新对象时,也没有设置 created 字段。 Mongoose 只是根据架构返回当前日期,即使它在文档中不存在。

所以,现在的问题变成了:如何确保使用 upsert 为参数中未提供的字段创建默认值?

【问题讨论】:

  • 您能否在问题中写下您的user 对象。这样我就可以尽力帮助你了。
  • @techxxx 请检查编辑。

标签: node.js mongodb mongoose mongodb-update


【解决方案1】:

findOneAndUpdate 只是发送一个 MongoDB findAndModify 请求(参见findOneAndUpdate)。这意味着它跳过了与模式设置器、获取器、默认值等相关的所有猫鼬魔法。验证仅在创建/保存时运行,因此解决此问题的方法是执行.findOne(),检查存在/创建一个新的一个,然后是.save()

see this issue for more discussion

编辑:

关于每次更改日期的第一个问题,您可以稍微更改架构。摆脱默认值,而是在声明架构后添加它:

UserSchema.pre("save", function (next) {
    if (!this.created) {
        this.created = new Date();
    }
    next();
});

这只会在created: 值不存在时创建一个日期,并且应该防止它每次更改创建日期(使用.save() 时)。

查看 Mongoose 中间件

【讨论】:

  • 非常感谢@cdbajorin,我已经采用了检查 findOne 的方法,如果它返回 null,则保存一个新条目。
【解决方案2】:

如果您的文档是使用findOneAndUpdate 创建的(在查询之前不存在)并且您没有在更新中提供该字段,则要为您的文档添加默认值,您应该使用setDefaultsOnInsert

upsertsetDefaultsOnInsert 都是true 时,如果没有找到记录并创建一个新记录,将设置默认值。 这跳过了必须检查记录是否存在的工作流程,如果不存在,则使用“保存”创建一个新记录,以确保设置了默认值。

我遇到了同样的问题(使用findOneAndUpdateupsert: true 创建的记录)并且字段的默认值未添加到记录中,即使它在架构中。 这只是关于在使用findOneAndUpdate 创建文档时添加默认值,而不是用于跳过“created”字段的更新。

例如

User.findOneAndUpdate({email: user.email}, user, {upsert: true, setDefaultsOnInsert:true}, ...)

【讨论】:

  • 请详细说明您的答案。我已经阻止它成为 NAA。您现在应该考虑改进它。见How to Answer
猜你喜欢
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-28
  • 2016-06-13
  • 2018-09-26
  • 1970-01-01
相关资源
最近更新 更多