简体   繁体   中英

How to Group within a group in the $push part in Mongo DB

Suppose we have the code :

EightWeekGamePlan.aggregate(
      [
        { $sort: { Week: 1 } },
        {
          $group: {
            _id: {
              LeadId: "$LeadId",
              BusinessName: "$BusinessName",
              PhoneNumberMasque: "$PhoneNumberMasque",
              City: "$City",
              Rooms: "$Rooms"
              // dateToString: { format: "%Y-%m-%d", date: "$InserDate" }
            },
            Weeks: {
              $push: {
                Week: "$Week",
                Status: "$Status",
                InsertDate: "$InsertDate",
                TargetClient: "$TargetedToBeClaimedByClientType",
                MaxClaims: "$TotalClaimsToBeClaimedByClientType",
                CurrentClaims: "$TotalClaimsLeftToBeClaimedByClientType"
              }
            }
          }
        }
      ]

I'm grouping an then $pushing into an array , however another group is required before passing back the data to the client : how can we group the Weeks array by Week ?

Please don't use another grouping of $Week in the first $group .

Example of the current answer (before the 2nd group), and I want to have it grouped again by the Week :

LeadId: "6823f5c6-244e-41aa-89eb-5d4d87fac068"
PhoneNumberMasque: "076-5465743856475"
BusinessName: "Something ... "
City: "Somewhere ..."
Rooms: 2
Weeks: Array(10): Array(10)
0: {Week: 1, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 1, MaxClaims: 1, …}
1: {Week: 1, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 2, MaxClaims: 2, …}
2: {Week: 1, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 3, MaxClaims: 2, …}
3: {Week: 2, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 2, MaxClaims: 5, …}
4: {Week: 3, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 3, MaxClaims: 5, …}
5: {Week: 4, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 4, MaxClaims: 5, …}
6: {Week: 5, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 5, MaxClaims: 5, …}
7: {Week: 6, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 6, MaxClaims: 5, …}
8: {Week: 7, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 7, MaxClaims: 5, …}
9: {Week: 8, Status: 1, InsertDate: "2019-12-27T08:44:26.000Z", TargetClient: 8, MaxClaims: 5, …}

In case you don't want to use additional $group stage you can take advantage of $reduce combined with $filter . $setUntion gives you an array of unique Week numbers and then using $filter you can bring matching documents from Weeks array into your result set, combining subdocuments using $concatArrays :

db.collection.aggregate([
    {
        $project: {
            Weeks: {
                $reduce: {
                    input: { $setUnion: "$Weeks.Week" },
                    initialValue: [],
                    in: {
                        $concatArrays: [
                            "$$value",
                            [{
                                WeekNum: "$$this",
                                Docs: { $filter: { input: "$Weeks", as: "w", cond: { $eq: [ "$$w.Week", "$$this" ] } } }
                            }]
                        ]
                    }
                }
            }
        }
    }
])

Mongo Playground

Although the added stage of @mickl seems to do the job, i would prefer to simply switch your $week field to from accumulator to your _id field of $group stage,

EightWeekGamePlan.aggregate(
      [
        {
          $group: {
            _id: {
              LeadId: "$LeadId",
              BusinessName: "$BusinessName",
              PhoneNumberMasque: "$PhoneNumberMasque",
              City: "$City",
              Rooms: "$Rooms"
              Weeks: "$Week",
            },
            Weeks: {
              $push: {
                Status: "$Status",
                InsertDate: "$InsertDate",
                TargetClient: "$TargetedToBeClaimedByClientType",
                MaxClaims: "$TotalClaimsToBeClaimedByClientType",
                CurrentClaims: "$TotalClaimsLeftToBeClaimedByClientType"
              }
            }
          }
        },
        { $sort: { "_id.Week": 1 } },
      ]

Note that here, your $sort stage as no real effect as first stage, but is more useful after grouping.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM