Skip to content
Advertisement

Mongo Organize by object inside aggregate request

My project is in nodeJs with express and i use mongoose for the request to my database mongoDb.

I have a model Media the structure is:

{
  "_id": {
    "$oid": "6354f982a11464ff4f7bac60"
  },
  "userId": {
    "$oid": "6353aa119d39ccbb3263123f"
  },
  "date": "2022-10-23",
  "base64": "data:image/png;base64,iVBORw0KGgoAAA....=",
  "label": "Noamount",
  "uriPath": "xxxx",
  "s3Path": "xxxx",
  "amount": 0,
  "__v": 0,
  "type": "tva"
}

Like you seen there is a field date, imagine that i have 3 medias on differents month:

{
  "date": "2022-10-23",
  "label": "monthTen",
  "type" : "tva",
  ... // Other property
},
{
  "date": "2022-09-10",
  "label": "monthNineFirst",
  "type" : "tva",
  ... // Other property
},
{
  "date": "2022-09-19",
  "label": "monthNineSecond",
  "type" : "other",
  ... // Other property
}

I want to output something like this:

// Ordery by type in first place and by month
// number like 9 = the month inside the date property
{
  tva: {
   9: [{ label: "monthNineFirst"... }],
   10: [{ label: "monthNineTen"... }]
  },
  other: {
   9: [{ label: "monthNineSecond"... }]
  }
}

Is found the property aggregate but i don’t understand it correctly.

I know how to dow that in JS it’s easy, but can i do that directly on the request with the property aggregate and $group?

There is what i have done so far https://mongoplayground.net/p/-vAbdnnqOfD

Advertisement

Answer

Here’s one way to do it by extending your mongoplayground.net start.

db.collection.aggregate([
  { // group all docs by month
    $group: {
      _id: {
        $month: {
          $dateFromString: {
            dateString: "$date",
            format: "%Y-%m-%d"
          }
        }
      },
      data: {"$push": "$$ROOT"}
    }
  },
  { // group all groups into a single doc
    "$group": {
      "_id": null,
      "groupData": {
        "$push": {
          // k,v for $arrayToObject
          "k": "$_id",
          "v": {
            "$sortArray": {
              "input": "$data",
              "sortBy": {"date": 1}
            }
          }
        }
      }
    }
  },
  {
    "$replaceWith": {
      "$arrayToObject": {
        "$map": {
          "input": {
            // sort by month
            "$sortArray": {
              "input": "$groupData",
              "sortBy": {"k": 1}
            }
          },
          "in": {
            "$mergeObjects": [
              "$$this",
              { // rewrite k as string
                "k": {"$toString": "$$this.k"}
              }
            ]
          }
        }
      }
    }
  }
])

Try it on mongoplayground.net.

1 People found this is helpful
Advertisement