Mongoose upsert不会创建默认架构属性

时间:2014-09-10 00:25:35

标签: node.js mongodb mongoose

示例文档架构:

var CompanySchema = Schema({
    created: { type: Date, default: Date.now },
    modified: { type: Date, default: Date.now },
    address: { type: String, required:true },
    name: { type: String, required:true }
});

我正在使用通用请求处理程序来编辑和创建“公司”文档:

exports.upsert = function(req, res) {
    helper.sanitizeObject(req.body);
    var company = {
        name: req.body.name,
        address: req.body.address
    };
    var id = req.body.id || new mongoose.Types.ObjectId();
    var queryOptions = {
        upsert: true
    };
    Company.findByIdAndUpdate(id, company, queryOptions).exec(function(error, result) {
        if(!error) {
            helper.respondWithData(req, res, {
                data: result.toJSON()
            });
        } else {
            helper.respondWithError(req, res, helper.getORMError(error));
        }
    });
};

但是使用此方法,在插入新文档时,createdmodified属性不会保存为默认值Date.now。现在我可以根据id的存在来调用Company.create,但我想知道为什么如果新文档中不存在属性,upsert不会使用默认值?

我正在使用Mongoose版本~3.8.10,

2 个答案:

答案 0 :(得分:33)

当发生任何“更新”系列方法(如findByIdAndUpdate)时,没有使用Mongoose的验证,中间件或默认值。它们仅通过拨打savecreate来调用。

原因是“更新”调用实际上是传递给本机驱动程序,而Mongoose只根据模式定义提供字段的类型转换。

Mongoose 4.0更新

Mongoose现在支持在updatefindOneAndUpdatefindByIdAndUpdate upsert期间创建新文档时设置默认值。将setDefaultsOnInsert选项设置为true以启用此选项。这使用$setOnInsert运算符在insert上创建默认值。

var queryOptions = {
    upsert: true,
    setDefaultsOnInsert: true
};
Company.findByIdAndUpdate(id, company, queryOptions).exec( ...

答案 1 :(得分:8)

您可以使用{ "$setOnInsert": { value: 31 } } Doc

参考:https://groups.google.com/forum/#!topic/mongoose-orm/WuJSqxPX8T8

语法:findOneAndUpdate([query], [doc], [options], [callback]) Doc

示例:

model.findOneAndUpdate(
      { username: 'john' },
      { "$setOnInsert": { points: '0' },
            $push: {
            "boards": {
                "account":req.body.account,
                "game":req.body.game                                        
            }
        }          
      { upsert: true},
      function(err, doc) {    

      });