Using update/aggregation ( since 4.2+) you can do something even better:
db.collection.update({
"_id": "accountId 1"
},
[
{
$set: {
codes: {
$cond: [
{
$in: [
"advantageCode 2",
"$codes.key"
]
},
{
$map: {
input: "$codes",
in: {
$mergeObjects: [
"$$this",
{
$cond: [
{
$eq: [
"$$this.key",
"advantageCode 2"
]
},
{
"dateBegin": "01/02/2020",
"dateEnd": "01/02/2021"
},
{}
]
}
]
}
}
},
{
$concatArrays: [
"$codes",
[
{
"key": "advantageCode 2",
"dateBegin": "01/02/2022",
"dateEnd": "01/02/2023"
}
]
]
}
]
}
}
}
])
Explained:
Update dateBegin and dateEnd for codes.key that matches , or if there is no match add the new codes object to the set.
Playground
Afcourse , if you only want to $addToSet if key is missing then you can do:
Playground2
The bulkWrite operation will look something like this:
bulkWrite([{updateOne: {
filter: { _id: commands[0].accountId },
update: [{ $set: { codes: { $cond: [ { $in: [commands[0].advantageCode,"$codes.key"]},{ $map: { input: "$codes",in: { $mergeObjects: [ "$$this", {}]}}},{$concatArrays: ["$codes",[{
"key": commands[0].advantageCode ,
"dateBegin": commands[0].dateBegin,
"dateEnd": commands[0].dateEnd
}
]
]
}
]
}
}
}
]
}}])
If you need to upsert document in case accountId is not found here is the option:
db.collection.update({
"_id": "accountId 2"
},
[
{
$set: {
codes: {
"$cond": [
{
$ne: [
{
$type: "$codes"
},
"missing"
]
},
{
$cond: [
{
$in: [
"advantageCode 3",
"$codes.key"
]
},
{
$map: {
input: "$codes",
in: {
$mergeObjects: [
"$$this",
{}
]
}
}
},
{
$concatArrays: [
"$codes",
[
{
"key": "advantageCode 3",
"dateBegin": "01/02/2022",
"dateEnd": "01/02/2023"
}
]
]
}
]
},
{
"key": "advantageCode 3",
"dateBegin": "01/02/2022",
"dateEnd": "01/02/2023"
}
]
}
}
}
],
{
upsert: true
})
Explained:
- In case accountId is not found insert new document.
- In case codes.key is not found insert new object with the new key to the codes array.
Playground3