I am trying to use $addToSet to insert new Objects into an Array in mongo using mongoose:
I have a two models:
var itemSchema = mongoose.Schema({
itemId: Number,
save_date: {type: Date, default: Date.now}
});
var UserSchema = new Schema({
...
items: [itemSchema]
});
var User = mongoose.model('User', UserSchema);
I would like to use mongoose to add an item into the items array, but only if that item does not exist.
Currently, using $addToSet is still adding duplicates because, I assume the save_date stamp is different for every item:
User.findByIdAndUpdate(
id,
{$addToSet: {item: {itemId: newItem} } },
{upsert: true},
function (err, saveItem){
if (err) {return handleError(err)};
res.send(saveItem);
}
);
Which results in a user entry:
"name": "Vinnie James"
"items" : [
{
"itemId" : 123,
"_id" : ObjectId("587b10259233c524454d745d"),
"save_date" : ISODate("2017-01-15T06:01:09.850Z")
},
{
"itemId" : 123,
"_id" : ObjectId("587b17398ed7052b1e5196bc"),
"save_date" : ISODate("2017-01-15T06:31:21.263Z")
}
]
Is it possible to check if the itemId exists before adding the entry, in order to avoid having two "itemId": 123 as seen above?
If there is a better way to structure the model to achieve the same result, I'm happy to consider that as well
Try this way:
User.findOneAndUpdate(
{_id: id, "items.itemId": {$nin:[newItem.itemId]}},
{$push: {items: newItem }},
{new: true}
function (err, updatedUser){
if (err) {return handleError(err)};
res.send(updatedUser);
}
);
$nin operator will ensure that there is not item in items with the same itemId of newItem. Then if it succeed the newItem will be added by $push operator. {new: true} tells mongo to pass the updated document in the provided callback