1

I need to update all the fields of a document in mongodb with random values:

Site.updateMany({siteID: undefined || null}, {$set: {siteID: shortid.generate()}});

shortid.generate() creates a random string. The issue with my code is that all the fields are setted with the same random string, which makes me think that the function is executed once and then updated to all fields.
How can I achieve to update all fileds with random strings?

1
  • 1
    You have to write JavaScript code to get the random string and update documents one at a time. Or you can use aggregation to generate different random numbers for all documents ans update them one at a time. Commented Jan 11, 2020 at 1:26

2 Answers 2

3

You've got couple of options :

On MongoDB v4.2 or above && If you're ok to store MongoDB's _id's string value(which is unique) try this ::

As .updateMany() in latest version accepts aggregation pipeline :

Site.updateMany(
    // Filtering documents to check siteID not exists & equals to null (just null check will make sure field doesn't exists as well)
    { siteID: null },
    [
        { $set: { siteID: { $toString: '$_id' } } }
    ])

On MongoDB below v4.2:

You need to first fetch and then update :

a) Fetch documents :

let response = Site.aggregate([{$match : {date : null}}, {$project :{siteID : {$toString : '$_id'}}}])

b) Update documents :

let bulkArr = [];
response.forEach(element => {
    bulkArr.push({
        updateOne: {
            "filter": { _id: element._id }, // Use mongoose.Types.ObjectId(element._id) if needed.
            "update": { '$set': { 'siteID': element.siteID } }
        }
    })
});

let updateResult = await Site.bulkWrite(bulkArr)
console.log('matchedCount ::', updateResult.matchedCount, 'modifiedCount ::', updateResult.modifiedCount)

Just in case if you don't want to store string value of _id, then in the Step a) you can just get _id's projected & in Step b) Create random string using :: generate-random-string-characters-in-javascript while iterating through array from Step 1).

Sign up to request clarification or add additional context in comments.

4 Comments

This set the property I selected to the ObjectID type instead of a string unfortunately { $set: { siteID: { $toString: '$_id' } } }
@fIwJlxSzApHEZIl Didn't get what you're saying!
after an hour or so I ended up with a working solution of my own. I made a post here stackoverflow.com/a/73667111/584947
@fIwJlxSzApHEZIl Not sure why 1st solution didn't work for you! But your solutions is same as the 2nd solution provided. It would be better to use BulkWrite to avoid multiple DB update calls!
0

You're right, the function is evaluated first and its result is passed to the query only once.

You will need to update each document separately. Alternatively you could use mapReduce to transform each document as you want and output the modified documents to another collection.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.