Luke Greenwood
Luke Greenwood

Reputation: 97

MongoDB Split document field into two fields

I have a MongoDB document with over 2.8m documents of common passwords (hashed in SHA1) and their popularity.

Currently I've imported the documents with the following schema

{"_id":"5ded1a559015155eb8295f48","password":"20EABE5D64B0E216796E834F52D61FD0B70332FC:2512537"}

Although I'd like to split this so I can have the popularity value and it would look something like this

{"_id":"5ded1a559015155eb8295f48","password":"20EABE5D64B0E216796E834F52D61FD0B70332FC","popularity":2512537}

Question is im unsure how I can split the password into two password, popularity using : to split the string

Upvotes: 4

Views: 2453

Answers (1)

mickl
mickl

Reputation: 49985

You can use Aggregation Framework to split current password into two fields. You need to start with $indexOfBytes to get the position of : and then you need $substr to create new fields based on evaluated position.

db.collection.aggregate([
    {
        $addFields: {
            colonPos: { $indexOfBytes: ["$password",":"] }
        }
    },
    {
        $addFields: {
            password: { $substr: [ "$password", 0, "$colonPos" ] },
            popularity: { $substr: [ "$password", "$colonPos", { $strLenBytes: "$password" } ]  }
        }
    },
    {
        $project: {
            colonPos: 0
        }
    }
])

Mongo Playground

As a last step you can use $out which takes all your aggregation results and writes them into new or existing collection.

EDIT: Alternative approach using $split (thank to @matthPen):

db.collection.aggregate([
    {
        $addFields: { 
            password: { $arrayElemAt: [ { "$split": [ "$password", ":"] }, 0 ] },
            popularity: { $arrayElemAt: [ { "$split": [ "$password", ":"] }, 1 ] }
        }
    }
])

Mongo Playground

Upvotes: 5

Related Questions