8

我有以下用户模型:

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

使用findOneAndUpdatewith的目的upsert: true是要么返回现有配置文件,要么创建一个新配置文件。它还会根据发布的数据更新任何字段。

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

编辑

来自数据库的示例对象:

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

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

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

4

2 回答 2

18

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

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

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

例如

User.findOneAndUpdate({email: user.email}, user, {upsert: true, setDefaultsOnInsert:true}, ...)
于 2018-01-03T09:38:55.120 回答
5

findOneAndUpdate simply sends a MongoDB findAndModify request (see findOneAndUpdate). What this means is that it skips all the mongoose magic involved with the schema setters, getters, defaults, etc. Validation is only run on create/save so the way around this is to do a .findOne(), check existence/create a new one, and then .save().

see this issue for more discussion

EDIT:

In regards to the first question about changing the date each time, you could change the schema a bit. Get rid of the default value, and instead add this after declaring the schema:

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

That will only create a date if the created: value is not present, and should prevent it from changing the creation date each time (when using .save()).

see Mongoose middleware

于 2014-11-11T15:42:53.290 回答