Hello,
I'm having an issue I'm sure others have encountered but I can't find the right solution. I have a collection with documents following this model:
{
id: "id",
field: "value",
items: [
{ id: "itemid", field: "value", ... },
...
]
}
My app gets notifications about new or updated items and I want to update the collection accordingly. Those notifications don't tell whether the item is actually new or just updated. So I would like to perform a findAndModify that :
- if no matching document exists, create one with the item
- if a matching document exists, but the item is not in it, add it to the array
- if a matching document exists, and the item is in the array, update it
I want a findAndModify because item notifications can happen very often, so to avoid conflicts or race conditions I want an atomic update.
I tried the following (not the exact syntax but you get the idea):
collection.findAndModify({
query: { id: item.collectionId, items: { $elemMatch: { id: item.itemId } } },
update: {
$setOnInsert: {
id: item.collectionId,
field: item.fieldValue,
items: [ { id: item.itemId, field: item.itemField } ]
},
$set: {
"items.$.field": item.itemField
}
},
upsert: true
});
Unfortunately I get a "have conflicting mods in update" error. I guess this is because I update items both in $set and $setOnInsert, but I couldn't find any other update command that works. I wish there were a $setOnUpdate operator...
Does anyone have an idea on how to achieve what I want atomically ?
Thanks,
Nicolas