Home > Back-end >  How to find and update a document in MongoDB
How to find and update a document in MongoDB

Time:01-30

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"
                  }
               }
            }
         }
      }
   }
])
  • Related