最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Mongoose - Increment Field On Subdoc if exists, else create new - Stack Overflow

programmeradmin2浏览0评论

What I am trying to do.

I have a userSchema that contains a list of operationCountSchemaobjects. What I am trying to do, is to create a static method that updates the count field on one of these operation count subdocuments if it exists (identified by a month_id) field. If an operationCountSchema document does not exist for the current month, it should create a new document. Is there a way to achieve this behaviour in mongoose? I have tried using upsert to no avail. How would one do this? Thanks.

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

Also, any suggestions on alternative ways in which this functionality can be achieved are wele.

What I am trying to do.

I have a userSchema that contains a list of operationCountSchemaobjects. What I am trying to do, is to create a static method that updates the count field on one of these operation count subdocuments if it exists (identified by a month_id) field. If an operationCountSchema document does not exist for the current month, it should create a new document. Is there a way to achieve this behaviour in mongoose? I have tried using upsert to no avail. How would one do this? Thanks.

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

Also, any suggestions on alternative ways in which this functionality can be achieved are wele.

Share Improve this question edited Jun 7, 2016 at 3:22 Anthony Dito asked May 30, 2016 at 5:34 Anthony DitoAnthony Dito 3,6803 gold badges33 silver badges59 bronze badges 3
  • Pass the values through static method and check whether the sub-document exist(using this keyword). If exist modify and call callback. Else create sub-document using this.sub-docment = <your-values> and call the callback. Once the callback is called use mongoose document save() method to save modified document. – n_rao Commented Jun 2, 2016 at 12:58
  • What does month_id needs to match to to increment the count? – Chinni Commented Jun 2, 2016 at 19:30
  • @Chinni month_id needs to match dateIdentifier. – Anthony Dito Commented Jun 2, 2016 at 23:05
Add a ment  | 

3 Answers 3

Reset to default 7

I think you want findOneAndUpdate() with upsert : true:

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

(untested)

You can do it in two steps, here is a example in mongo shell:

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

First, make sure the subdoc exists, if not just create one use $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" : "[email protected]",
    "password" : "balalalala",
    "operation_counts" : [
        {
            "month_id" : "2016-05",
            "count" : 6
        },
        {
            "month_id" : "2016-06",
            "count" : 0
        }
    ]
}

Then, increment the count field.

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" : "[email protected]",
    "password" : "balalalala",
    "operation_counts" : [
        {
            "month_id" : "2016-05",
            "count" : 6
        },
        {
            "month_id" : "2016-06",
            "count" : 1
        }
    ]
}

So you can have a mongoose.find() or mongoose.findOne() and check if the sub-document exists. If it doesn't we can create the a new object and if it does, we can increment and save.

Here I'm using mongoose.findOne(). Refer to the docs 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";
            });
        }
    });
};

Let me know if I got your question worng or didn't address something.

发布评论

评论列表(0)

  1. 暂无评论