在 meteor 中使用 mongo 聚合到集合中的总数 unlocked/locked

Using mongo aggregate in meteor to total unlocked/locked in collection

所以,我有一个存储与用户相关的文档的集合,其结构如下:

{_id: "hofjew233332j4", userId: "fhewojfw34324", achievementUnlocked: true };

我想做的是使用聚合和下划线能够按用户 ID 对文档进行分组,然后计算他们的记录中有多少百分比已解锁设置为 true,这样生成的文档将如下所示:

{_id: "fhewojfw34324(userId)", unlockPercentage: 40 (achievementUnlocked: true / all docs) }

我是否可以只检索一次文档来执行此操作?

我个人甚至不会为这里的聚合而烦恼,因为数据看起来微不足道。为每个用户 and/or "game" 数据维护一个 "locked" 和 "unlocked" 成就数组会更有效率。

拿这样的文件:

{
    "_id": "hofjew233332j4", 
    "userId": "fhewojfw34324",
    "gameId": "v3XWHHvFSHwYxxk6H",
    "achievementsCount": 5,
    "locked": ["One","Two","Four","Five"],
    "lockedCount": 4,
    "unlocked": ["Three"]
    "unlockedCount": 1
}

因此,您通常会在此处对每个用户和 "game" 初始化所有 "locked" 成就,但在这种情况下,我们将在 "unlocked" 中显示一个成就。还要注意 "count" 字段反映了每个数组中存在的条目数。

到 "unlock" 另一个成就,那么您只需执行更新以从 "locked" 数组中删除并插入到 "unlocked" 数组中,同时保持 "count" 值:

Achievements.update(
   { 
       "userId": "fhewojfw34324",
       "gameId": "v3XWHHvFSHwYxxk6H",
       "locked": "Four",
       "unlocked": { "$ne": "Four" }
   },
   {
       "$push": { "unlocked": "Four" },
       "$pull": { "locked": "Four" },
       "$inc": {
           "lockedCount": -1,
           "unlockedCount": 1
       }
   }
)

将文档更改为此状态:

{
    "_id": "hofjew233332j4", 
    "userId": "fhewojfw34324",
    "gameId": "v3XWHHvFSHwYxxk6H",
    "achievementsCount": 5,
    "locked": ["One","Two","Five"],
    "lockedCount": 3,
    "unlocked": ["Three","Four"]
    "unlockedCount": 2
}

这是一个非常简单的模式,因为每次更新都会维护正确的值和数据。如果您想要 "percentage" 之类的信息,那么这很简单:

Achievements.aggregate([
    { "$project": {
        "userId": 1,
        "gameId": 1,
        "percentUnlocked": { "$divide": [ "$unlockedCount", "$achivementsCount" ] }
])

或者只是在客户端代码中应用该数学运算。

此模型还使 "real" 您可能想要进行的聚合更加简单,并且信息范围更大。另外,边走边计算比要求 "add up" 数据作为一个单独的过程更有效。

首先按计数 achievementUnlocked true 计数分组,然后在项目中使用以下聚合计算 percentage

db.collectionName.aggregate([{
    "$group": {
        "_id": "$userId",
        "achievementUnlockedTrueCount": {
            "$sum": {
                "$cond": {
                    "if": {
                        "$eq": ["$achievementUnlocked", true] //count achievementUnlocked = true count 
                    },
                    "then": 1,
                    "else": 0
                }
            }
        },
        "totalCount": {
            "$sum": 1 // get total count of grouped documents 
        }
    }
}, {
    "$project": {
        "unlockPercentage": {
            "$multiply": [{
                "$divide": ["$achievementUnlockedTrueCount", "$totalCount"] //used this in project to caculate %
            }, 100]
        }
    }
}]).pretty()