Update documents with different values

Hi,

I would update all documents of a collection by adding a field called probability which is a random number between 0 and 1. In particular, assuming I know that in a collection there are exactly 3 documents, I would like to perform something like that:

let filterDoc1 = {_id: "idDoc1"}
let filterDoc2 = {_id: "idDoc2"}
let filterDoc3 = {_id: "idDoc3"}

let probabilities = [0,0.5,1]
db.collection.updateOne(filterDoc1, {$set: {probability: probabilities[0]}})
db.collection.updateOne(filterDoc2, {$set: {probability: probabilities[1]}})
db.collection.updateOne(filterDoc3, {$set: {probability: probabilities[2]}})

In this case I will do an update opation for each document, so it is very inefficient (almost impossible) if there are a lot of documents in the collection (as in my case). For this reason, I would do that operation in one single round-trip time (or something that does not depend on the number of documents in the collection). What is the best way in order to accomplish this purpose?

Hi @Matteo_Tarantino,

How about this? It’s using the updates with aggregation pipelines.

db.coll.updateMany({}, [{$set: {rand_value: {$rand: {}}}}])

Here it is in action:

test [direct: primary] test> db.coll.insertMany([{},{},{}])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("6228db48fb402cbc4b85ebef"),
    '1': ObjectId("6228db48fb402cbc4b85ebf0"),
    '2': ObjectId("6228db48fb402cbc4b85ebf1")
  }
}
test [direct: primary] test> db.coll.find()
[
  { _id: ObjectId("6228db48fb402cbc4b85ebef") },
  { _id: ObjectId("6228db48fb402cbc4b85ebf0") },
  { _id: ObjectId("6228db48fb402cbc4b85ebf1") }
]
test [direct: primary] test> db.coll.updateMany({}, [{$set: {rand_value: {$rand: {}}}}])
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 3,
  modifiedCount: 3,
  upsertedCount: 0
}
test [direct: primary] test> db.coll.find()
[
  {
    _id: ObjectId("6228db48fb402cbc4b85ebef"),
    rand_value: 0.606824267273937
  },
  {
    _id: ObjectId("6228db48fb402cbc4b85ebf0"),
    rand_value: 0.08368945539792201
  },
  {
    _id: ObjectId("6228db48fb402cbc4b85ebf1"),
    rand_value: 0.8383115137796183
  }
]

In pure Aggregation Pipeline, we could also use $merge:

[
  {
    '$set': {
      'rand_value': {
        '$rand': {}
      }
    }
  }, {
    '$merge': {
      'into': 'coll', 
      'on': '_id', 
      'whenMatched': 'merge', 
      'whenNotMatched': 'fail'
    }
  }
]

Cheers,
Maxime.

1 Like

I understand that I have given the wrong example with the probabilistic value. Assume that you need to add a generic object, each different for each document, something like: {field1: value1, field2: value}.

There is something that suits for this case?

Well then I guess you could assign a probability to each field/value couple, get a random value with $rand and then use $switch so you could pick one of the value randomly?

Would you be kind enough to give me an example query for this following case study?

let valuesToInsert = [
   {
      "newField": {
          key1: "value1"
      }
   },
   {
      "newField": {
          key2: "value2"
      }
   }
]

The goal is to update each document with one of the two possible newField value

Something like this maybe?

test [direct: primary] test> db.coll.insertMany([{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("6228e4cc551b7b41d956268b"),
    '1': ObjectId("6228e4cc551b7b41d956268c"),
    '2': ObjectId("6228e4cc551b7b41d956268d"),
    '3': ObjectId("6228e4cc551b7b41d956268e"),
    '4': ObjectId("6228e4cc551b7b41d956268f"),
    '5': ObjectId("6228e4cc551b7b41d9562690"),
    '6': ObjectId("6228e4cc551b7b41d9562691"),
    '7': ObjectId("6228e4cc551b7b41d9562692"),
    '8': ObjectId("6228e4cc551b7b41d9562693"),
    '9': ObjectId("6228e4cc551b7b41d9562694"),
    '10': ObjectId("6228e4cc551b7b41d9562695"),
    '11': ObjectId("6228e4cc551b7b41d9562696"),
    '12': ObjectId("6228e4cc551b7b41d9562697"),
    '13': ObjectId("6228e4cc551b7b41d9562698"),
    '14': ObjectId("6228e4cc551b7b41d9562699"),
    '15': ObjectId("6228e4cc551b7b41d956269a"),
    '16': ObjectId("6228e4cc551b7b41d956269b"),
    '17': ObjectId("6228e4cc551b7b41d956269c"),
    '18': ObjectId("6228e4cc551b7b41d956269d"),
    '19': ObjectId("6228e4cc551b7b41d956269e")
  }
}

test [direct: primary] test> db.coll.updateMany({},[{$set: {
...   fries: {$switch: {
.....     branches: [
.....       { case: { $lt : [ { $rand : {} }, 0.3 ] }, then: "small" },
.....       { case: { $lt : [ { $rand : {} }, 0.6 ] }, then: "medium" },
.....     ],
.....     default: "large"
.....   }}
... }
... }])
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 20,
  modifiedCount: 20,
  upsertedCount: 0
}
test [direct: primary] test> db.coll.find()
[
  { _id: ObjectId("6228e4cc551b7b41d956268b"), fries: 'small' },
  { _id: ObjectId("6228e4cc551b7b41d956268c"), fries: 'large' },
  { _id: ObjectId("6228e4cc551b7b41d956268d"), fries: 'small' },
  { _id: ObjectId("6228e4cc551b7b41d956268e"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d956268f"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d9562690"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d9562691"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d9562692"), fries: 'small' },
  { _id: ObjectId("6228e4cc551b7b41d9562693"), fries: 'small' },
  { _id: ObjectId("6228e4cc551b7b41d9562694"), fries: 'large' },
  { _id: ObjectId("6228e4cc551b7b41d9562695"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d9562696"), fries: 'large' },
  { _id: ObjectId("6228e4cc551b7b41d9562697"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d9562698"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d9562699"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d956269a"), fries: 'small' },
  { _id: ObjectId("6228e4cc551b7b41d956269b"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d956269c"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d956269d"), fries: 'medium' },
  { _id: ObjectId("6228e4cc551b7b41d956269e"), fries: 'large' }
]
2 Likes

Very clear, thank you!

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.