Cesar Jr Rodriguez
Cesar Jr Rodriguez

Reputation: 1821

Update many fields in mongodb with random values

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?

Upvotes: 1

Views: 3520

Answers (2)

whoami - fakeFaceTrueSoul
whoami - fakeFaceTrueSoul

Reputation: 17915

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).

Upvotes: 3

MikkolidisMedius
MikkolidisMedius

Reputation: 4844

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.

Upvotes: 0

Related Questions