Mongoose - 增量字段在Subdoc上存在,否则创建新的

时间:2016-05-30 05:34:59

标签: javascript node.js mongodb mongoose

我想做什么。

我有userSchema,其中包含operationCountSchema个对象的列表。我想要做的是创建一个静态方法,如果它存在(由count)字段标识,则更新其中一个操作计数子文档上的month_id字段。如果当前月份不存在operationCountSchema文档,则应创建新文档。有没有办法在猫鼬中实现这种行为?我试过使用upsert无济于事。怎么会这样做?感谢。

CODE

var operationCountSchema = mongoose.Schema({
    month_id: String,
    count: { type: Number, default: 0 }
}, {_id : false});

var userSchema = mongoose.Schema({
    username : { type: String, unique: true, required: true },
    email: { type: String, unique: true, required: true },
    password: String,
    operation_counts: [operationCountSchema]
});

userSchema.statics.incrementOperationCount = function(userID, callback) {
    var currDate = new Date();
    var dateIdentifier = currDate.getFullYear() + "-" + currDate.getMonth();
    //NEED TO INCREMENT OPERATION COUNT IF ONE FOR MONTH EXISTS, 
    //ELSE IF IT DOES NOT EXIST, CREATE A NEW ONE.
}

此外,欢迎任何关于可以实现此功能的替代方式的建议。

3 个答案:

答案 0 :(得分:3)

我认为您希望findOneAndUpdate()upsert : true

operationCountSchema.findOneAndUpdate({
  month_id : dateIdentifier,
}, { 
  $inc : { count : 1 }
}, {
  upsert : true
}, callback);

(未测试的)

答案 1 :(得分:2)

您可以分两步完成,这是mongo shell中的示例:

mongos> db.collection.findOne()    
{
    "username" : "mark",
    "email" : "admin@example.com",
    "password" : "balalalala",
    "operation_counts" : [
        {
            "month_id" : "2016-05",
            "count" : 6
        }
    ]
}

首先,确保子网存在,如果不是只创建一个使用$addToSet

mongos> db.collection.update({username:"mark", "operation_counts.month_id": {$ne:"2016-05"}}, {$addToSet: {"operation_counts":{month_id: "2016-05", count:0}}})
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
// only update when the subdoc of specified month not exists
mongos> db.collection.update({username:"mark", "operation_counts.month_id": {$ne:"2016-06"}}, {$addToSet: {"operation_counts":{month_id: "2016-06", count:0}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

mongos> db.collection.findOne()
{
    "_id" : ObjectId("575636c21e9b27fe715df654"),
    "username" : "mark",
    "email" : "admin@example.com",
    "password" : "balalalala",
    "operation_counts" : [
        {
            "month_id" : "2016-05",
            "count" : 6
        },
        {
            "month_id" : "2016-06",
            "count" : 0
        }
    ]
}

然后,增加count字段。

mongos> db.collection.update({username:"mark", "operation_counts.month_id": "2016-06"}, {$inc:{ "operation_counts.$.count":1 }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

mongos> db.collection.findOne()
{
    "_id" : ObjectId("575636c21e9b27fe715df654"),
    "username" : "mark",
    "email" : "admin@example.com",
    "password" : "balalalala",
    "operation_counts" : [
        {
            "month_id" : "2016-05",
            "count" : 6
        },
        {
            "month_id" : "2016-06",
            "count" : 1
        }
    ]
}

答案 2 :(得分:1)

因此,您可以拥有mongoose.find()mongoose.findOne()并检查子文档是否存在。如果不是,我们可以创建一个新对象,如果有,我们可以增加并保存。

我在这里使用mongoose.findOne()。请参阅文档here

userSchema.statics.incrementOperationCount = function(userID, callback) {
var currDate = new Date();
var dateIdentifier = currDate.getFullYear() + "-" + currDate.getMonth();
    //NEED TO INCREMENT OPERATION COUNT IF ONE FOR MONTH EXISTS, 
    //ELSE IF IT DOES NOT EXIST, CREATE A NEW ONE.
    operationCountSchema.findOne({'month_id': dateIdentifier}, function(err, subDoc) {
        // If there is an error in finding the document, catch them
        if(err) {
            // Handle errors
            return err;
        }
        // If you find a document, increment the `count` and save
        if(subDoc) {
            subDoc.count += 1;
            subDoc.save(function(err2) {
                if(err2) {
                    // Handle errors
                    return err2;
                } else {
                    return "Success";
                }
            });
        } 
        // If no document is found, create a new one
        else {
            // Populate the values to create the object
            var data = {
                "month_id": dateIdentifier,
                "count": 0
            };
            operationCountSchema.create(data, function(err3, subDoc) {
                if(err3) {
                    // Handle errors
                    return err3;
                }
                // Else return success
                return "Success";
            });
        }
    });
};

如果我提出问题或者没有解决问题,请告诉我。