Skip to content
Advertisement

Mongo Group By query

I have data stored in a Mongo collection that is structured like this:

 {
    "numberAtPending" : 3,
    "numberAtInProgress" : 5,
    "numberAtCancelled" : 1,
    "numberAtShipped" : 50,
    "timeOfRequest" : ISODate("2022-01-10T12:52:15.813Z"),
    "requestingSupplier" : "SUPPLIER_1",
},
{
    "numberAtPending" : 5,
    "numberAtInProgress" : 3,
    "numberAtCancelled" : 4,
    "numberAtShipped" : 35,
    "timeOfRequest" : ISODate("2022-01-15T09:11:02.992Z"),
    "requestingSupplier" : "SUPPLIER_1",
},
{
    "numberAtPending" : 12,
    "numberAtInProgress" : 3,
    "numberAtCancelled" : 1,
    "numberAtShipped" : 21,
    "timeOfRequest" : ISODate("2022-01-10T14:21:55.221Z"),
    "requestingSupplier" : "SUPPLIER_2",
}

I wish to construct a query that would let me sum up each count in each entry and group by requestingSupplier.

For example, I would like to answer the question, for the month of January ’22, what was the sum of each entity and get a response similar to:-

"TotalNumberAtPending": 300
"TotalNumberAtInProgress" : 150,
"TotalNumberAtCancelled" : 70,
"TotalNumberAtShipped" : 400
"Supplier" : "SUPPLIER_1",

"TotalNumberAtPending": 230
"TotalNumberAtInProgress" : 110,
"TotalNumberAtCancelled" : 40,
"TotalNumberAtShipped" : 300
"Supplier" : "SUPPLIER_2",

Any help most appreciated! thanks and regards

Advertisement

Answer

You can try this query (also I’m assuming the output you show is an example and not the real values because I don’t know from where can you get 300, 150, 400…)

So, try this:

You have two options to match values in the range of two dates. If you want to input the name of the month and the year you can try something like:

  • Use $expr and $eq with $year and $month. And then you can use as input exaclty the number of the desired month or year.
{
  "$match": {
    "$expr": {
      "$and": [
        {
          "$eq": [
            {
              "$month": "$timeOfRequest"
            },
            1
          ]
        },
        {
          "$eq": [
            {
              "$year": "$timeOfRequest"
            },
            2022
          ]
        }
      ]
    }
  }
}

Or you can match by the date range. If you want to get all documents from 01-2022 you can use this $match stage where the range is from the first second of January (equal) to the first second of February (not equal, so i.e. is the last second of January).

{
  "$match": {
    "timeOfRequest": {
      "$gte": ISODate("2022-01-01T00:00:00Z"),
      "$lt": ISODate("2022-02-01T00:00:00Z")
    }
  }
}

So, with the filter done you only need to use $group like this to generate the desired fields values.

{
  "$group": {
    "_id": "$requestingSupplier",
    "TotalNumberAtPending": {
      "$sum": "$numberAtPending"
    },
    "TotalNumberAtInProgress": {
      "$sum": "$numberAtInProgress"
    },
    "TotalNumberAtCancelled": {
      "$sum": "$numberAtCancelled"
    },
    "TotalNumberAtShipped": {
      "$sum": "$numberAtShipped"
    },
    "Supplier": {
      "$first": "$requestingSupplier"
    }
  }
}

Example here and here

2 People found this is helpful
Advertisement