5

I have collection with name products with almost 100k documents. I want to introduce a new key called secondaryKey with unique value uuid in all the documents. I do this using nodejs.

Problem I am facing:-

When I try the below query,

db.collection('products').updateMany({},{"$set":{secondaryKey: uuid()}});

Here it updates all the documents with same uuid value,

I try with loop to update document one by one,but here issues is I don't have filter value in updateOne because I want to update all the documents.

Can anyone please help me here. Thanks :)

abinas patra
  • 359
  • 3
  • 21

3 Answers3

5

If you are using MongoDB version >= 4.4 You can try this:

db.products.updateMany(
    {},
    [
        {
            $set: {
                secondaryKey: {
                    $function: {
                        body: function() {
                            return UUID().toString().split('"')[1];
                        },
                        args: [],
                        lang: "js"
                    }
                }
            }
        }
    ]
);

Output

[
  {
    "_id": ObjectId("..."),
    "secondaryKey": "f41b15b7-a0c5-43ed-9d15-69dbafc0ed29"
  },
  {
    "_id": ObjectId("..."),
    "secondaryKey": "50ae7248-a92e-4b10-be7d-126b8083ff64"
  },
  {
    "_id": ObjectId("..."),
    "secondaryKey": "fa778a1a-371b-422a-b73f-8bcff865ad8e"
  }
]
Dheemanth Bhat
  • 4,269
  • 2
  • 21
  • 40
  • Btw, This question brought me here: https://stackoverflow.com/questions/66894033/set-id-to-a-new-uuid-using-addfields – Dheemanth Bhat Mar 31 '21 at 20:10
  • 1
    This only works if security.javascriptEnabled is enabled which is a requirement and not preferable method. "For a mongos instance, see security.javascriptEnabled configuration option or the --noscripting command-line option starting in MongoDB 4.4." – Bitfinicon Apr 04 '22 at 07:18
1

Since it's not the same value you want to put in each document you have to use the loop.

In your loop, you have to update the current document of the iteration. So you have to filter with the _id in the updateOne

AlexisG
  • 2,476
  • 3
  • 11
  • 25
  • any way, we can achieve through `updateMany` by just incrementing the `secondaryKey`, I can use `uuid` later as well, just wanted a unquie `secondaryKey` for each document, because looping will be heavier process. – abinas patra Mar 18 '21 at 10:58
0

The above reply didn't work for me. Plus, it compromises security when you enable javascript on your database (see here $function and javascript enabling on database). The best way is to not overload your server, do your work on local as below:

const { nanoid, customAlphabet } = require('nanoid') 

async function asdf() {


const movies = await client.db("localhost").collection("productpost");
var result2 = []

let result = await movies.find({}).toArray()
result.forEach(element => {
    const nanoid = customAlphabet('1234567890', 10)
    console.log(element.price)
    element.price = 4
    element.id = nanoid()
    result2.push(element)
});
console.log("out reult2", result2)
await movies.deleteMany({})
await movies.insertMany(result2) 
})

It will delete any objects on your collections and update with the new ones. Using nanoid as uniqueids.

This is the database object array after adding unique id:

{  "_id": {    "$oid": "334a98519a20b05c20574dd1"  },  "attach": "[\"http://localhost:8000/be/images/2022/4/bitfinicon.png\"]",  "title": "jkn jnjn",  "description": "jnjn",  "price": 4,  "color": "After viewing I am 48.73025772956596% more satisfied with life.",  "trademark": "",  "category": "[]",  "productstate": "Published",  "createdat": {    "$date": "2022-04-03T17:40:54.743Z"  },  "language": "en"}

P.S: Please backup your collection before doing this or filter the array on your needs for not going through all collection.

Bitfinicon
  • 1,045
  • 1
  • 8
  • 22