Search code examples
mongodbmgo

MongoDB: How To use $group aggregation to get all data using similar field?


I am trying to perform a query using golang mgo to effectively get similar values from a join.
My structure is like this:

 result: [
    {
        "_id" : 1,
        "booking_id" : 96,
        "provider_id" : 20,
        "time" : NumberLong(1541158790),
        "arrival_time" : NumberLong(1541158863)
    },
    {
        "_id" : 3,
        "booking_id" : 96,
        "provider_id" : 20,
        "time" : NumberLong(1541158908),
    },
    {
        "_id" : 4,
        "booking_id" : 95,
        "provider_id" : 20,
        "type" : "abc",
        "time" : NumberLong(1541163544),
        "location" : {
            "lat" : 30.711858,
            "lng" : 76.729649
        },
    },
    {
        "_id" : 8,
        "booking_id" : 95,
        "provider_id" : 20,
        "type" : "aaa",
    }
] 

I have to group data of similar booking_id, Now how can I get a data of simlilar booking id using $group aggregation.I want a data in a following structure::

result: [
    0:[
        {
            "_id" : 1,
            "booking_id" : 96,
            "provider_id" : 20,
            "time" : NumberLong(1541158790),
            "arrival_time" : NumberLong(1541158863)
        },
        {
            "_id" : 3,
            "booking_id" : 96,
            "provider_id" : 20,
            "time" : NumberLong(1541158908),
        },
    ],
    1:[
        {
            "_id" : 4,
            "booking_id" : 95,
            "provider_id" : 20,
            "type" : "abc",
            "time" : NumberLong(1541163544),
            "location" : {
                "lat" : 30.711858,
                "lng" : 76.729649
            },
        },
        {
            "_id" : 8,
            "booking_id" : 95,
            "provider_id" : 20,
            "type" : "aaa",
        }
    ]
] 

I have created a function which is returing result of this collection and using $group like this:

query := []bson.M{
        {"$group": bson.M{
            "_id": bson.M{"booking_id": "$booking_id"},
            "count": bson.M{"$sum": 1}}}}
pipe := getCollection.Pipe(query)
err = pipe.All(&result)

But it will return this output to me:

[
    {
        "id": 0,
        "booking_id": 0,
        "provider_id": 0
    }
]

Here I am mentioning only two booking ids data, I have 1000 of booking id records in my database. I want to show data grouped by booking id, Is it possible using mongodb $group aggregation?? Or if not then how can I achieve this thing in mongodb using mgo package for golang.


Solution

  • You can use $group and $$ROOT, which references the document currently being processed in the pipeline. Your aggregation would be something like:

    { 
        $group: {
          _id: '$booking_id',
          items: {
            $push: '$$ROOT'
          }
        }
    }
    

    Which would result in this:

     [
        {
            "_id": 95,
            "items": [
               {
                "_id" : 1,
                "booking_id" : 96,
                "provider_id" : 20,
                "time" : NumberLong(1541158790),
                "arrival_time" : NumberLong(1541158863)
              },
              {
                "_id" : 3,
                "booking_id" : 96,
                "provider_id" : 20,
                "time" : NumberLong(1541158908),
              },
            ]
       }
    ],
    ...
    

    EDIT:

    If you want to show both booking_id and provider_id, you can group by these both fields and project the data the way you want. Like this:

    [
    {
        $group: {
            _id: { 'booking_id': '$booking_id', 'provider_id': '$provider_id' },
            items: { $push: '$$ROOT' }
        }
    },
    {
        $project: {
            _id: 0,
            booking_id: '$_id.booking_id',
            provider_id: '$_id.provider_id',
            items: 1 
        }
    }
    ]
    

    Giving this structure:

    [
    {
        "booking_id": 96,
        "provider_id": 20,
        "items": [
           {
            "_id" : 1,
            "booking_id" : 96,
            "provider_id" : 20,
            "time" : NumberLong(1541158790),
            "arrival_time" : NumberLong(1541158863)
          },
          {
            "_id" : 3,
            "booking_id" : 96,
            "provider_id" : 20,
            "time" : NumberLong(1541158908),
          },
        ]
     }
    ],
    ...