sabu
sabu

Reputation: 91

Mongo DB- Update document field if a particular field has more than one document matches

Scenario

Example Mongo DB documents Doc 1 { _id 123 Customer: customer A State: TX City: Houston checksum: 1111 IsBundlled: }

Doc 2 { _id 1234 Customer: customer B State: TX City: Houston checksum: 1111 IsBundlled: }

Doc 3 { _id 12345 Customer: customer c State: NY City: Buffalo checksum: 2222 IsBundlled:

}

Checksum field is populated in app code using State and City fields.

Problem

Populate IsBundled field for each document to true, if a checksum matches more than 1 documents. In our case 1st and 2nd documents needs to updated with isBundled: true . Instead of adding this logic in application code, I am looking for better solutions using aggregation pipeline

Also how to perform this aggregation in app code via Spring Boot Mongo AggregationUpdate class

Upvotes: 3

Views: 213

Answers (2)

Aniket Raj
Aniket Raj

Reputation: 2141

$merge is available from versions greater than MongoDB 4.4

As $merge at the end of aggregation pipeline is necessary to update the collection through aggregation.

For more information about $merge : https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge/

$group: To group the matching documents.
$set: To modify the document
$gt: To check if greater than condition
$replaceRoot: To replace the current document structure by another.

MongoDB Playground link : https://mongoplayground.net/p/pV_UbQ-ADby

db.collection.aggregate([
  {
    $group: {
      _id: "$checksum",
      count: {
        $sum: 1
      },
      bundles: {
        $push: "$$ROOT"
      }
    }
  },
  {
    "$unwind": "$bundles"
  },
  {
    $set: {
      "bundles.IsBundled": {
        $gt: [
          "$count",
          1
        ]
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": "$bundles"
    }
  }
])

Upvotes: 2

R2D2
R2D2

Reputation: 10727

Maybe something like this:

db.collection.aggregate([
{
"$group": {
  "_id": "$checksum",
   "toUpdate": {
    "$addToSet": "$_id"
   },
  cnt: {
    $sum: 1
    }
  }
  },
  {
   $match: {
    cnt: {
      $gt: 1
   }
  }
 }
 ]).toArray().forEach(function(d){ db.collection.update({_id:{$in:d.toUpdate}},{$set:{ IsBundled:"true" }})   },{multi:true})

aggregation playground

Explained:

  1. Group on checksum and get document _id per same checksum
  2. Filter checksum matching more then one document
  3. Loop over the result to update all the documents with duplicated checksum with IsBundled: true

Upvotes: 1

Related Questions