Convert Object to Array For a User In MongoDB

Viewed 3497

I have multiple users in my collection and each user has an object of sessions shown below

{
  user: 'adam',
  sessions: {
   key: some-value,
   key: some-value
  }
} 
{
  user: 'chris',
  sessions: {
   key: some-value,
   key: some-value
  }
} 

I fetch the document on the basis of the user name. let us say i want the sessions of adam.

So I run db.collection.find({ user: 'Adam' }) which gives me full document of adam. Now I want the sessions of 'Adam' but the sessions object should be converted into an array of objects like this :

{
 user: 'adam'
 sessions : [ { key: value },{ key: value } ]
}

I want to convert the sessions of user into an object that means i want to do $objectToArray but on a specific username not the full collection.

Just the user I want.

Explanation:

I am running node as backend and i have a route called 'getuserdata' which gets data for a specific user based on the username. So when i will hit that route with username adam and it will get the data from the DB. The sessions of adam should come in an array of objects like shown above instead of an object which is in the db.

What i am doing

I am running a for-in loop on the back-end to convert them into array of objects but it is slow.

3 Answers

You can do it using $map in project part,

  • $map input sessions as array to convert using $objectToArray,
  • inside map convert array of object key and value to $arrayToObject
db.collection.find(
{ user: "adam" },
{
  user: 1,
  sessions: {
    $map: {
      input: { $objectToArray: "$sessions" },
      in: { $arrayToObject: [["$$this"]] }
    }
  }
})

Playground

//run from mongodb client
//sample user data preparation
> db.users15.find();
{ "_id" : ObjectId("5f4fbfbc3372ab5da3a605ac"), "user" : "adam", "sessions" : { "key1" : 1123, "key2" : 1124 } }
{ "_id" : ObjectId("5f4fbfbc3372ab5da3a605ad"), "user" : "chris", "sessions" : { "key1" : 2122, "key2" : 2134 } }
// Mongo query, variable defined an user for dynamic passing in match condition
> var v_user = "adam"
> db.users15.aggregate([
...  {$match:{user:v_user}},
...  {$project:{user:1,
...             sessionArray:{$objectToArray:"$sessions"}
...         }
...     }
... ]);
//output showing conversion from session object to array for key value pair
{ "_id" : ObjectId("5f4fbfbc3372ab5da3a605ac"), "user" : "adam", "sessionArray" : [ { "k" : "key1", "v" : 1123 }, { "k" : "key2", "v" : 1124 } ] }
>
//Further,the mongo query gives correct output for nested objects as well.
//Example below.
> db.users15.find().pretty();
{
        "_id" : ObjectId("5f4fbfbc3372ab5da3a605ac"),
        "user" : "adam",
        "sessions" : {
                "key1" : 1123,
                "key2" : 1124
        }
}
{
        "_id" : ObjectId("5f4fbfbc3372ab5da3a605ad"),
        "user" : "chris",
        "sessions" : {
                "key1" : 2122,
                "key2" : 2134
        }
}
{
        "_id" : ObjectId("5f5069ed3372ab5da3a605ae"),
        "user" : "sriny",
        "sessions" : {
                "key1" : 2122,
                "key2" : 2134,
                "key3" : {
                        "server1" : 2344,
                        "server2" : 9999
                }
        }
}
>
> var v_user = "sriny"
> db.users15.aggregate([
...  {$match:{user:v_user}},
...  {$project:{user:1,
...             sessionArray:{$objectToArray:"$sessions"}
...         }
...     }
... ]).pretty();
{
        "_id" : ObjectId("5f5069ed3372ab5da3a605ae"),
        "user" : "sriny",
        "sessionArray" : [
                {
                        "k" : "key1",
                        "v" : 2122
                },
                {
                        "k" : "key2",
                        "v" : 2134
                },
                {
                        "k" : "key3",
                        "v" : {
                                "server1" : 2344,
                                "server2" : 9999
                        }
                }
        ]
}
>

Take for example this object

const obj = { 
  key1: "value1",
  key2: "value2"
}

We can map this to pattern [ { key1: value1 }, { key2: value2 } ] using a map on the object keys

const arrayFromObj = Object.keys(obj).map(value => { 

    return { value: obj[value] }
  
})
Related