汇总和分配随机赢家的更好方法

时间:2019-06-05 20:30:58

标签: node.js mongodb aggregation-framework

我正在尝试使用以下数据集汇总一组交易,并选择每个年级的赢家。优胜者是从年级中随机选择的。

{ "_id" : ObjectId("5ce6fb4b3d1be918e574500a"),
"eventId" : ObjectId("5ce2f540bf126322a6be559b"),
"donationAmt" : 32,
"ccTranId" : "HzP4B",
"firstName" : "Jason",
"lastName" : "Jones",
"grade" : "1",
"teacher" : "Smith, Bob",
"studentId" : 100 },

{ "_id" : ObjectId("5ce6fb4b3d1be918e574500b"),
"eventId" : ObjectId("5ce2f540bf126322a6be559b"),
"donationAmt" : 15,
"ccTranId" : "HzP4A",
"firstName" : "Joey",
"lastName" : "Jones",
"grade" : "1",
"teacher" : "Smith, Jane",
"studentId" : 200 },

{ "_id" : ObjectId("5ce6fb4b3d1be918e574500c"),
"eventId" : ObjectId("5ce2f540bf126322a6be559b"),
"donationAmt" : 25,
"ccTranId" : "HzP4D",
"firstName" : "Carrie",
"lastName" : "Jones",
"grade" : "2",
"teacher" : "Smith, Sally",
"studentId" : 300 }

我正在使用此脚本进行汇总。

Donation.aggregate([
                      {
                        $match: {
                          eventId: mongoose.Types.ObjectId(eventId)
                        }
                      },
                      {
                        "$group": {
                          "_id": "$studentId",
                          "first": { "$first": "$firstName" },
                          "last": { "$first": "$lastName" },
                          "grade": { "$first": "$grade" },
                          "teacher": { "$first": "$teacher" }
                        }
                      },
                      {
                        "$group": {
                          "_id": "$grade",
                          "students": {
                            $push: '$$ROOT'
                          }
                        }
                      }
                      , { $sort: { _id: 1 } }
                    ])

输出使我可以使用它。然后,我遍历每个元素,并将子文档中的一名学生分配为获胜者。

double group似乎很草率,最好在$ project子句中执行一个表达式以随机分配获胜者。

有没有更清洁的方法?

    {  
      "_id":"1",
      "students":[  
         {  
            "_id":100,
            "first":"Jason",
            "last":"Jones",
            "grade":"1",
            "teacher":"Smith, Bob"
         },
         {  
            "_id":200,
            "first":"Joey",
            "last":"Jones",
            "grade":"1",
            "teacher":"Smith, Jae"
         }
          ]
},
{
       "_id":"2",
         students":[ .... ]
         },

1 个答案:

答案 0 :(得分:1)

随机性意味着您需要获得不可预测的结果。可以在MongoDB中为您提供帮助的唯一操作员是$sample。不幸的是,您无法对数组进行采样。您所能做的就是应用过滤条件,然后对该过滤后的数据集运行{ $sample: { size: 1 } }

db.col.aggregate([
    {
        $match: {
            eventId: ObjectId("5ce2f540bf126322a6be559b"),
            grade: "2"
        }
    },
    {   $sample: { size: 1 }  }
])

要使其更加有用,您可以利用$facet并在一个查询中为每个年级运行多个样本:

db.col.aggregate([
    {
        $match: {
            eventId: ObjectId("5ce2f540bf126322a6be559b")
        }
    },
    {
        $facet: {
            winner1: [
                { $match: { grade: "1" } },
                {   $sample: { size: 1 }  }
            ],
            winner2: [
                { $match: { grade: "2" } },
                {   $sample: { size: 1 }  }
            ]
            // other grades ...
        }
    }
])