node.js - 聚合和分配随机获胜者的更好方法

标签 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 } }
                    ])

输出让我可以使用它。然后,我迭代每个元素并将子文档中的一名学生指定为获胜者。

双组看起来很草率,最好在 $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":[ .... ]
         },

最佳答案

随机意味着您需要获得不可预测的结果。 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 ...
        }
    }
])

关于node.js - 聚合和分配随机获胜者的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56467575/

相关文章:

javascript - 找不到模块 : Error: Can't resolve 'react-dom/client'

mongodb错误。如何解决 mongoDB 中的错误?

javascript - Ubuntu 为 Node.js 打开/解锁端口

mongodb - 节点红色MongoDB限制需要一个整数

mongodb - 如何使用mongodb聚合

mongodb - 如何在不使用 $facet 的情况下组合两个 MongoDB 聚合管道查询的结果并对组合结果执行另一个聚合查询?

mongodb - 使用 MongoDB 按多个值进行 Golang 聚合组

python - 如何使用 MongoDB 聚合将多个字符串字段连接成单个字段?

javascript - Node JS 基本路由器被覆盖

node.js - 在编写自定义 TypeScript 定义文件时出现错误 "Module ' name'resolves to an untyped module at..."