What I try to do is fairly simple, I have an array inside a document ;
"tags": [
{
"t" : "architecture",
"n" : 12
},
{
"t" : "contemporary",
"n" : 2
},
{
"t" : "creative",
"n" : 1
},
{
"t" : "concrete",
"n" : 3
}
]
I want to push an array of items to array like
["architecture","blabladontexist"]
If item exists, I want to increment object's n
value (in this case its architecture
),
and if don't, add it as a new Item (with value of n=0
) { "t": "blabladontexist", "n":0}
I have tried $addToSet
, $set
, $inc
, $upsert: true
with so many combinations and couldn't do it.
How can we do this in MongoDB?
With MongoDB 4.2 and newer, the update method can now take a document or an aggregate pipeline where the following stages can be used:
$addFields
and its alias$set
$project
and its alias$unset
$replaceRoot
and its alias$replaceWith
.Armed with the above, your update operation with the aggregate pipeline will be to override the
tags
field by concatenating a filteredtags
array and a mapped array of the input list with some data lookup in the map:To start with, the aggregate expression that filters the tags array uses the
$filter
and it follows:which produces the filtered array of documents
Now the second part will be to derive the other array that will be concatenated to the above. This array requires a
$map
over themyTags
input array asThe above
$map
essentially loops over the input array and checks with each element whether it's in thetags
array comparing thet
property, if it exists then the value of then
field of the subdocument becomes its currentn
value expressed withelse add the default document with an n value of 0.
Overall, your update operation will be as follows
Your final update operation becomes:
I don't believe this is possible to do in a single command.
MongoDB doesn't allow a $set (or $setOnInsert) and $inc to affect the same field in a single command.
You'll have to do one update command to attempt to $inc the field, and if that doesn't change any documents (n = 0), do the update to $set the field to it's default value.