Get Aggregate Data In MongoDB

Viewed 120

enter image description here

Here is the mongo DB document structure provided above in the image. There you can see we have got a xmlRequests array under pages array (Pages is array of objects). So each session has pages array containing some objects

What I want to do:

Let us say we have 10 documents with same structure as shown in the image above. I want the aggregate (unified) array of all the pages under all the sessions in one array. In simple words I want the pages array of all the sessions in one array. (Aggregate)

Like this:

{
 pages : [] // array containing all the objects of request arrays under each session.
}

I need a one unified requests[ ] array containing all the requests of all the sessions in one single array. I tried using db.collection.aggregate([ ]) but I don't know how to get the nested values in a document and unify all of them in one single array of objects.

Mongo Code Snippet

{
 "user": "abc",
 "sessions": {
 "12345": {
    "pages": [
        {
            requests: [ {name: 'request1'}]
        }
    ]
    },
  "23456": {
    "pages": [
        {
            requests: [ {name: 'request1'}]
        }
    ]
    }
    }
}

{
  "user": "xyz",
  "sessions": {
  "12345": {
    "pages": [
        {
            requests: [ {name: 'request1'}]
        }
    ]
    },
   "23456": {
    "pages": [
        {
            requests: [ {name: 'request1'}]
        }
    ]
     }
    }
   }

FETCH ALL REQUEST ARRAYS IN THE COLLECTION AND COMBINE THEM INTO ONE ARRAY

2 Answers

You can start with $objectToArray in order to retrieve values from unknown keys. Then you need a couple of $reduce / $concatArrays pairs to flatten arrays of arrays. $group can be used to collect all requests into a single document:

db.collection.aggregate([
    {
        $project: {
            pages: {
                $reduce: {
                    input: { $objectToArray: "$sessions" },
                    initialValue: [],
                    in: {
                        $concatArrays: [
                            "$$value",
                            {
                                $reduce: {
                                    input: "$$this.v.pages",
                                    initialValue: [],
                                    in: { $concatArrays: [ "$$value", "$$this.requests" ] }
                                }
                            }
                        ]
                    }
                }
            }
        }
    },
    {
        $group: {
            _id: null,
            pages: { $push: "$pages" }
        }
    },
    {
        $project: {
            pages: {
                $reduce: {
                    input: "$pages",
                    initialValue: [],
                    in: { $concatArrays: [ "$$value", "$$this" ] }
                }
            }
        }
    }
])

Mongo Playground

Give this a try. Basically we unwind the first array pages so that we get a huge list of pages. Then we group all xml requests arrays into one big array. And then we merge them into one array and return an object with a key requests contains the final array

    .aggregate([{
         $unwind: “$pages”,
    },
    {
         $group: {
              _id: null,
              xmlRequests: { $push: "$xmlRequests"}
          }
    },
    {
        $project: {
             _id: 0,
             requests: {
                $reduce: {
                    input: "$xmlRequests",
                    initialValue: [],
                     in: {
                         $concatArrays: [ "$$this", "$$value"]
                     }
                 }
             }
         }
    }])
Related