SQB
SQB

Reputation: 4078

Set _id to a new UUID using $addFields

Well, someone done goofed. Wasn't me, but I get to fix it. What I need to do, is replace the _id of each and every document in the collection with a new UUID.

My plan was aggregating the entire collection, use $addFields to replace the _id, then merge it back into itself, replacing the records. Fortunately, there is a secondary (composite) key I can use for merging, so I'm good there — I think, because I haven't gotten there yet.

The problem I face is generating a unique (that's kinda the point of it) UUID during the $addFields stage.

db.foo.agregate([
    {
        $addFields: {
            // I really just need the UUID string itself, hence the split
            '_id': UUID().toString().split('"')[1]
        }
    }
    // here's where the merge would go
])

The problem here is that UUID() is called only once, so I get all the same IDs. That's not quite what I want.

Now the tedious way would be to do this one by one, from a loop. But is there a way to do this from within an aggregation pipeline in one go?


Now I found this question asking basically the same question, but it was solved by not using an UUID, using sequential keys instead, so it really isn't an answer to my question.

Upvotes: 3

Views: 3857

Answers (2)

Dheemanth Bhat
Dheemanth Bhat

Reputation: 4452

So this answer is just to generate unique UUIDs by calling UUID() from a $function. Try this:

db.collectionName.aggregate([
    {
        $addFields: {
            _id: {
                $function: {
                    body: function() {
                        return UUID().toString().split('"')[1];
                    },
                    args: [],
                    lang: "js"
                }
            }
        }
    }
])

btw, its only works in MongoDB version >= 4.4. Output:

/* 1 */
{
    "_id" : "5dc9316a-50a8-4013-8090-06fc66cdce9f",
    "dummy" : "data"
},

/* 2 */
{
    "_id" : "062ebc8f-4455-4a81-a9e0-34f6c7132cab",
    "dummy" : "data"
},

/* 3 */
{
    "_id" : "94eef4b8-9c0e-4910-a1cb-58443a63a036",
    "dummy" : "data"
}

Upvotes: 4

D. SM
D. SM

Reputation: 14490

If what you need to do is

What I need to do, is replace the _id of each and every document in the collection with a new UUID.

... and you can use ObjectIds instead of UUIDs, then:

  • Project out the _id
  • $out into a new collection

The server should generate new _ids for each document during the insert.

Then:

  • Drop the original collection
  • Rename the new collection into the original name

Upvotes: 1

Related Questions