I am having a similar collection
db={
collectionA: [
{
"id": ObjectId("63b7c24c06ebe7a8fd11777b"),
"uniqueRefId": "UUID-2023-0001",
"products": [
{
"productIndex": 1,
"isProdApproved": false,
"productCategory": ObjectId("63b7c24c06ebe7a8fd11777b"),
"productOwners": [
{
_id: ObjectId("63b7c2fd06ebe7a8fd117781"),
iApproved: false
},
{
_id: ObjectId("63b7c2fd06ebe7a8fd117782"),
iApproved: false
}
]
},
{
"productIndex": 2,
"isProdApproved": false,
"productCategory": ObjectId("63b7c24c06ebe7a8fd11777b"),
"productOwners": [
{
_id: ObjectId("63b7c2fd06ebe7a8fd117781"),
iApproved: false
},
{
_id: ObjectId("63b7c2fd06ebe7a8fd117783"),
iApproved: false
}
]
},
{
"productIndex": 3,
"productCategory": "",
"productOwners": ""
}
]
}
]
}
I want to find the productOwner whose _id is 63b7c2fd06ebe7a8fd117781 in the productOwners and update the isApproved and isprodApproved to true. Other data will remain as it is.
I have tried this but it is only updating the first occurance
db.collectionA.update(
{
_id: ObjectId('63b7c24c06ebe7a8fd11777b'),
'products.productOwners._id': ObjectId('63b7c2fd06ebe7a8fd117781'),
},
{ $set: { 'products.$.productOwners.$[x].isApproved': true } },
{ arrayFilters: [{ 'x._id': ObjectId('63b7c2fd06ebe7a8fd117781') }] }
);
CodePudding user response:
As per the mongo documentation for update
you would need to set multi
to true in order to update multiple documents. Otherwise only the first hit will be updated.
https://www.mongodb.com/docs/manual/reference/method/db.collection.update/
By default, the db.collection.update() method updates a single document. Include the option multi: true to update all documents that match the query criteria.
If you want to update multi documents at once, you should probably use updateMany
directly. See: https://www.mongodb.com/docs/manual/reference/method/db.collection.updateMany/
CodePudding user response:
This one should work:
db.collection.updateMany({},
[
{
$set: {
products: {
$map: {
input: "$products",
as: "product",
in: {
$cond: {
if: { $eq: [{ $type: "$$product.productOwners" }, "array"] },
then: {
$mergeObjects: [
"$$product",
{ isProdApproved: { $in: [ObjectId("63b7c2fd06ebe7a8fd117781"), "$$product.productOwners._id"] } },
{
productOwners: {
$map: {
input: "$$product.productOwners",
as: 'owner',
in: {
$mergeObjects: [
"$$owner",
{ iApproved: { $eq: ["$$owner._id", ObjectId("63b7c2fd06ebe7a8fd117781")] } }
]
}
}
}
}
]
},
else: "$$product"
}
}
}
}
}
}
]
)
However, the data seem to be redundant. Better update only products.productOwners.iApproved
and then derive products.isProdApproved
from nested elements:
db.collection.aggregate([
{
$set: {
products: {
$map: {
input: "$products",
as: "product",
in: {
$cond: {
if: { $eq: [{ $type: "$$product.productOwners" }, "array"] },
then: {
$mergeObjects: [
"$$product",
{ isProdApproved: { $anyElementTrue: ["$$product.productOwners.iApproved"] } },
]
},
else: "$$product"
}
}
}
}
}
}
])