Mongoose - increment a field value in nested array

僤鯓⒐⒋嵵緔 提交于 2019-12-12 05:17:45

问题


I'm new to Mongoose and MongoDB and am trying to implement a scenario where I have to update a field value residing in a nested array.

For example, my DB entry is as follows:

{
    "_id" : ObjectId("581999ecf97860b77c1625f6"),      // this is userID
    "username" : "test",
    "__v" : 0,
    "polls" : [
            {
                    "url" : "xxxx",
                    "question" : "city or united",
                    "_id" : ObjectId("581999ec3ba2b15ad7fbcd50"),    //this is questionID
                    "option" : [
                            {
                                    "votes" : 0,
                                    "value" : "city",
                                    "_id" : ObjectId("581999ec3ba2b15ad7fbcd52")    //this is optionID
                            },
                            {
                                    "votes" : 0,
                                    "value" : "united",
                                    "_id" : ObjectId("581999ec3ba2b15ad7fbcd51")    //this is optionID
                            }
                    ]
            },
            {
                    "url" : "yyyy",
                    "question" : "chelsea or arsenal",
                    "_id" : ObjectId("58199d0ef11835685d3f41b7"),
                    "option" : [
                            {
                                    "votes" : 0,
                                    "value" : "chelsea",
                                    "_id" : ObjectId("58199d0ef11835685d3f41b9")
                            },
                            {
                                    "votes" : 0,
                                    "value" : "arsenal",
                                    "_id" : ObjectId("58199d0ef11835685d3f41b8")
                            }
                    ]
            }
    ]
}

I need to increment the votes of a particular option whenever it is selected from the front-end.

Below is what I've tried to implement so far but without success.

PollsSchema.methods.submitVote = function(id, callback){
var increment = { $inc: { 'polls.option.$.votes': 1 } };
var query = { 
    '_id': id.userID,
    'polls._id': id.questionID, 
    'polls.option._id': id.optionID
};

return this.model('Poll').update(query, increment, callback);
};

Below is my schema:

var PollsSchema = new Schema({
username: String,
polls: [
    {
        question: String,
        option: [
            {
                value: String,
                votes: Number
            }
        ],
        url: String
    }
]
});

Is there something that I'm doing incorrectly over here?

Thank you for your time and suggestions.


回答1:


You've the hit the Mongo db limitation where it doesn't support the nested array placeholder replacement. The positional operator can only be used for one level. So if you were to update the question like polls.$.question under polls, it will work fine. Also, mongo db doesnt have support for multiple placeholder something like polls.$.option.$.votes.

As pointed in the comment you can view that jira defect. Now coming to a workaround.

You can flatten your options so we can have it inside the polls. Something like this below. As long as you have unique id for question and option you should always can resolve to unique record.

{
    "_id": ObjectId("581999ecf97860b77c1625f6"), // this is userID
    "username": "test",
    "__v": 0,
    "polls": [{
        "url": "xxxx",
        "question": "city or united",
        "_id": ObjectId("581999ec3ba2b15ad7fbcd50"), //this is questionID
        "votes": 0,
        "value": "city",
        "option_id": ObjectId("581999ec3ba2b15ad7fbcd52") //this is optionID
    }, {
        "url": "xxxx",
        "question": "city or united",
        "_id": ObjectId("581999ec3ba2b15ad7fbcd50"), //this is questionID
        "votes": 0,
        "value": "united",
        "option_id": ObjectId("581999ec3ba2b15ad7fbcd51") //this is optionID
    }]
}

Now you can use something like this to increment the votes.

PollsSchema.methods.submitVote = function(id, callback) {
    var increment = {
        $inc: {
            'polls.$.votes': 1
        }
    };
    var query = {
        '_id': id.userID,
        'polls._id': id.questionID,
        'polls.option_id': id.optionID
    };

    return this.model('Poll').update(query, increment, callback);
};

Other option is to use aggregate pipeline and find the item and then update that returned object.



来源:https://stackoverflow.com/questions/40379369/mongoose-increment-a-field-value-in-nested-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!