Poperton
Poperton

Reputation: 2246

How to group orders by data range in MongoDB?

Suppose I have a collection like this:

[
  {
    "_id": ObjectId("5e3dd3d57f8bc30a7513e843"),
    "deleted": true,
    "date": "01/01/2020"
    "total": 3
  },
  {
    "_id": ObjectId("5e3dd3e97f8bc30a7513e99b"),
    "date": "02/01/2020",
    "deleted": false,
    "total": 11
  },
  {
    "_id": ObjectId("5e3dd3e97f8bc30a75137635"),
    "date": "15/02/2020",
    "deleted": false,
    "total": 5
  },
  {
    "_id": ObjectId("5e3dd3e97f8bc30a75131725"),
    "date": "18/02/2020",
    "deleted": false,
    "total": 7
  },
  {
    "_id": ObjectId("5e3dd3e97f8bc30a75131725"),
    "date": "03/03/2020",
    "deleted": false,
    "total": 9
  }
]

I need to merge these orders by a range to receive something like this:

{
"january": [order1, order2],
"february": [order3, order4],
"march": [order5]
}

of course I don't need the words "january, february" etc specifically, just something that let me group by data ranges. Something like this:

db.sales.aggregate( [
   { $group: { date: { "$gte": new Date(req.query.minDate), "$lte": new Date(req.query.maxDate) }, mergedOrders: { ?? } } }
])

which is not near a valid group aggregate call.

So, how do I group orders by data range? (I need to get, for each data range, the entire array of orders in that data range, as they are, without excluding fields)

Upvotes: 1

Views: 40

Answers (2)

whoami - fakeFaceTrueSoul
whoami - fakeFaceTrueSoul

Reputation: 17925

You can try this :

 db.sales.aggregate([
    { $match: { date: { "$gte": new Date(req.query.minDate), "$lte": new Date(req.query.maxDate) } } },
    {
        $group: {
            _id: {
                $month: {
                    $dateFromString: {
                        dateString: '$date',
                        format: "%d/%m/%Y"
                    }
                }
            }, mergedOrders: { $push: '$$ROOT' }
        }
    }, {
        $addFields: {
            _id: {
                $let: {
                    vars: {
                        monthsInString: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec']
                    },
                    in: {
                        $arrayElemAt: ['$$monthsInString', '$_id']
                    }
                }
            }
        }
    }])

Test : MongoDB-Playground

Upvotes: 1

Ryker
Ryker

Reputation: 802

You can use $group operator to group data based on a particular value in field. Then you may use push operator to have array of those values.

db.sales.aggregate([
    $match: {
        date: { "$gte": new Date(req.query.minDate), "$lte": new Date(req.query.maxDate) }
    },
    $group : {
        _id: "$date",
        orders: {
            $push: {
                deleted: "$deleted",
                total: "$total"       
             }
        }
    },
    $project: {
      _id: 1,
    orders: 1
   }
)];

Upvotes: 0

Related Questions