I have those kind of documents:
{
"_id": "accountId 1",
"codes": [
{
"key": "advantageCode 1",
"dateBegin": "01/02/2012",
"dateEnd": "01/02/2013"
},
{
"key": "advantageCode 2",
"dateBegin": "01/02/2012",
"dateEnd": "01/02/2013"
}
]
}
I would like to add a code in codes if it doesn't exist. I have tried this:
bulkWrite([{updateOne: {
filter: { _id: commands[0].accountId },
update: {$addToSet: {codes: {key: commands[0].advantageCode, dateBegin: commands[0].dateBegin, dateEnd: commands[0].dateEnd}}},
upsert: true
}}])
My problem is that the object is always added into the set, even if the key property already exists. It is normal (because it is another reference), but I would like to know how to rebase the $addToSet to the key of the objects.
I need the request to be a bulkwrite, because i gather many different requests.
CodePudding user response:
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.
Afcourse , if you only want to $addToSet if key is missing then you can do:
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.