mongoose. update record

44 views
Skip to first unread message

Ruslan Matkovsky

unread,
Nov 23, 2015, 4:35:41 PM11/23/15
to mongodb-user
Hi everyone!
I have one problem with update some records using mongoose.
There is a Scheme in my project
var itemSchema = new Schema({
            item: {type: Number, ref: 'Item'},
            channelID: String,
            isRefunded: Boolean,
            bonus: Boolean
        });

var schema = new Schema({
    _id: Number,
    username:                 { type: String, index: { unique: true, sparse: true } },
    playerData: [
            {
              gameId: Number,
              purchasedItems:       [itemSchema]
            }
    ]
};

UserModel.model = mongoose.model( 'User', schema );

I need to update record below UserModel.model.playerData[].purchasedItems[].channelId and using query of find UserModel.model._id: Number and UserModel.model.playerData.gameId: Number 

How can I do it?

Wan Bachtiar

unread,
Dec 7, 2015, 8:27:33 AM12/7/15
to mongodb-user

I need to update record below UserModel.model.playerData[].purchasedItems[].channelId and using query of find UserModel.model._id: Number and UserModel.model.playerData.gameId: Number
How can I do it?

Hi Ruslan,

If by update you mean inserting a new purchasedItem, you can utilise $push or $addToSet. For example using mongoose, your schema, and $push it would be :

UserModel.update(
    {'_id': 123, 'playerData.gameId': 456}, 
    {'$push': 
        {'playerData.$.purchasedItems': 
            { item: 123, channelID: "foobar", isRefunded:true, bonus:true }
        }
    }, 
    function(err){
        /* Handle Error */
        console.log(err);
    }
);

The above will insert a new purchasedItem document into the purchasedItems array.


If you are wanting to change a value of a particular channelID, you would need another value to filter the purchasedItems array in your find query. i.e. item.

Also currently (v3.0) you won’t be able to update using $set with nested arrays. There is an open ticket in MongoDB jira tracker SERVER-831 for this, feel free to watch or upvote for updates.

As an example work around, you can use findOne(), modify then save :

UserModel.findOne(
    {'_id': 123, 'playerData.gameId': 456}, 
    function(err, user){
        /* For each playerData elements */
        user.playerData.forEach(function(pData){
            /* For each purchasedItems elements */
            pData.purchasedItems.forEach(function(pItem){
                /* Find the element you would like to update */
                if (pItem.item == 001){
                    pItem.channelID = 'new channel'
                }
            })
        });
        /* Update document */
        user.save(function(err){
            /* Handle error */
            if(err){console.error(err);}
        })
    }
);

Alternatively, you can modify your schema to use sub-document rather than array for playerData. You may lose the ability to use $push and $addToSet, but it will simplify your application updates/queries.
For example:

{ _id: 123,
  username: 'foobar',
  playerData: {
    /* Use the gameId as the key of playerData sub-document. */
    "123": {
        purchasedItems:[ {item:123, channelId: "foobar"} ]
    },
    "456": {
        purchasedItems:[]
    }
}}


Kind regards,

Wan.


Reply all
Reply to author
Forward
0 new messages