MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

GroupBy plusieurs colonnes dans MongoDB

Suivez la requête d'agrégation ci-dessous :

db.shifts.aggregate([{ 
    //this get the day of week and converts them into sunday, saturday
    $project: {
        jobId:1,
        hourlyRate:1, 
        dayOfWeek: { $dayOfWeek: "$from" }, 
        workedHours: {$divide:[{ $subtract: ["$to", "$from"] }, 3600000]}, 
        saturday:{$floor: {$divide:[{ $dayOfWeek: "$from" }, 7]}},
        sunday:{$floor: {$divide:[{$abs:{$subtract:[{ $dayOfWeek: "$from" }, 7]}}, 6]}},
    }
}, {
    //based on the values of sunday and saturday gets the value of weekday
    $project: {
        jobId:1,
        workedHours:1,
        hourlyRate:1,
        saturday:1,
        sunday: 1,
        weekday:{$abs: {$add:["$sunday","$saturday", -1]}},
    } 
}, {
    //here calculates the earnings for each job
    $group:{
        _id:"$jobId",
        sundayEarnings:{$sum: {$multiply:["$sunday", "$hourlyRate", "$workedHours"]}},
        saturdayEarnings:{$sum: {$multiply:["$saturday", "$hourlyRate", "$workedHours"]}},
        weekdayEarnings:{$sum: {$multiply:["$weekday", "$hourlyRate", "$workedHours"]}},
        totalEarnings: {$sum:{$multiply:["$hourlyRate", "$workedHours"]}},
        totalWorkedHours: {$sum: "$workedHours"}
    }
}, {
    //and finally calculates the total jobs earnings
    $group:{
        _id:null,
        jobs:{$push:{
            jobId: "$_id",
            sundayEarnings: "$sundayEarnings",
            saturdayEarnings: "$saturdayEarnings",
            weekdayEarnings: "$weekdayEarnings",
            totalEarnings: "$totalEarnings",
            totalWorkedHours: "$totalWorkedHours"
        }},
        totalJobsEarning: {$sum: "$totalEarnings"}
    }
}])
  1. Le premier $project l'agrégation donne soit 0 soit 1 valeurs à saturday et sunday basé sur le dayOfWeek valeur en effectuant plusieurs calculs arithmétiques.
  2. Deuxième $project l'agrégation calcule le weekday La valeur de est basée sur le saturday et sunday valeurs.
  3. Le premier $group calcule les gains pour chaque jour dans chaque travail.
  4. Enfin le deuxième $group l'agrégation calcule la somme des gains de tous les emplois.

Tester

Voici ma contribution :

{
    "_id" : ObjectId("5885a1108c2fc432d649647d"),
    "from" : ISODate("2017-01-24T06:21:00Z"),
    "to" : ISODate("2017-01-24T08:21:00Z"),
    "jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
    "hourlyRate" : 32
}
{
    "_id" : ObjectId("5885a1108c2fc432d649647e"),
    "from" : ISODate("2017-01-25T06:21:00Z"),
    "to" : ISODate("2017-01-25T08:21:00Z"),
    "jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
    "hourlyRate" : 32
}
{
    "_id" : ObjectId("5885a1108c2fc432d649647f"),
    "from" : ISODate("2017-01-26T06:21:00Z"),
    "to" : ISODate("2017-01-26T08:21:00Z"),
    "jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
    "hourlyRate" : 32
}
{
    "_id" : ObjectId("58870cfd59dfb6b0c4eadd72"),
    "from" : ISODate("2017-01-28T06:21:00Z"),
    "to" : ISODate("2017-01-28T08:21:00Z"),
    "jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
    "hourlyRate" : 32
}
{
    "_id" : ObjectId("58870dc659dfb6b0c4eadd73"),
    "from" : ISODate("2017-01-29T06:21:00Z"),
    "to" : ISODate("2017-01-29T08:21:00Z"),
    "jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
    "hourlyRate" : 32
}

La requête d'agrégation ci-dessus donne le résultat suivant :

{
    "_id" : null,
    "jobs" : [
        {
            "jobId" : ObjectId("586d7d6acfc7e05669d6e2c8"),
            "sundayEarnings" : 64,
            "saturdayEarnings" : 64,
            "weekdayEarnings" : 192,
            "totalEarnings" : 320,
            "totalWorkedHours" : 10 
        }
    ],
    "totalJobsEarning" : 320
}

Dans les jobs tableau il n'y a qu'un seul travail car la collection de documents de décalages est référencée au même jobId . Vous pouvez essayer ceci avec différents jobId s et cela vous donnera différents emplois avec des revenus totaux.