将Upsert更新为true时未设置默认值



我为用户提供了以下模型:

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);

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

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

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"
}

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

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

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

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

我也遇到过同样的问题(用findOneAndUpdateupsert: true创建的记录),并且字段的默认值没有添加到记录中,即使它在模式中。这只是关于在使用findOneAndUpdate创建文档时添加默认值,而不是跳过"已创建"字段的更新。

例如

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

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

有关的更多讨论,请参阅此问题

编辑:

关于每次更改日期的第一个问题,您可以稍微更改一下模式。去掉默认值,而是在声明模式之后添加它:

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

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

请参阅Mongoose中间件

最新更新