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.