【问题标题】:Having trouble writing a MongoDB aggregation query that requires the use of grouping编写需要使用分组的 MongoDB 聚合查询时遇到问题
【发布时间】:2019-08-15 18:00:00
【问题描述】:

我有一个集合,其中存储了用户活动数据,这些数据与用户对选定的关键字列表投赞成票还是反对票有关,因为它们与标题目录相关。我需要在 Mongo 中执行一个聚合查询,它为我提供与所有用户的标题相关联的每个关键字的累积分数 - 投票表示赞成票:true,反对票表示反对票:false

使用 unwind 运算符作为我的第一步,然后是 group by,但这就是我迷失的地方,因为我不确定是否按 titleId、keyword 和 vote 的组合进行分组;只是titleId 和关键字或只是titleId。这是集合中数据的示例 -

期望在聚合查询的末尾看到一个按 titleId 分组的文档,其中包含一个对象数组,其中每个对象包含一个关键字以及该关键字在该标题的上下文中的累积投票总数。

{ 
    "_id" : ObjectId("5d2eb0b20e91d1941540e2b5"), 
    "titleId" : "111222", 
    "userId" : "993f1e69-c6b0-44eb-a8a6-5db5dc42d425", 
    "activity" : [
        {
            "keyword" : "Road Trip", 
            "vote" : true
        }, 
        {
            "keyword" : "Friendship", 
            "vote" : true
        },
        {
            "keyword" : "Family Movie", 
            "vote" : true
        }
    ]
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d38fd270e91d1941559bee0"), 
    "titleId" : "111222", 
    "userId" : "f92c7118-8930-4d30-8e07-8363737a6866", 
    "activity" : [
        {
            "keyword" : "Road Trip", 
            "vote" : false
        }, 
        {
            "keyword" : "Adventure", 
            "vote" : true
        }, 
        {
            "keyword" : "Family Movie", 
            "vote" : true
        }
    ]
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d38fd270e91d1941559bee0"), 
    "titleId" : "111222", 
    "userId" : "f92c7118-8930-4d30-8e07-8363737a6866", 
    "activity" : [
        {
            "keyword" : "Road Trip", 
            "vote" : false
        }, 
        {
            "keyword" : "Adventure", 
            "vote" : false
        }, 
        {
            "keyword" : "Family Movie", 
            "vote" : false
        }
    ]
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d2eb0b20e91d1941540e2b5"), 
    "titleId" : "444222", 
    "userId" : "993f1e69-c6b0-44eb-a8a6-5db5dc42d425", 
    "activity" : [
        {
            "keyword" : "Educational film and videos", 
            "vote" : true
        }, 
        {
            "keyword" : "Space", 
            "vote" : true
        }
    ]
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d38fd270e91d1941559bee0"), 
    "titleId" : "444222", 
    "userId" : "f92c7118-8930-4d80-8e07-8363737a6866", 
    "activity" : [
        {
            "keyword" : "Action", 
            "vote" : false
        }, 
        {
            "keyword" : "Adventure", 
            "vote" : false
        }, 
        {
            "keyword" : "Sci Fi", 
            "vote" : true
        }
    ]
}

希望看到一个按 titleId 分组的文档和一组对象,其中每个对象包含一个关键字以及该关键字在该标题的上下文中的累积投票总数。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    以下查询可以得到我们预期的输出:

    db.collection.aggregate([
        {
            $unwind:"$activity"
        },
        {
            $group:{
                "_id":{
                    "titleId":"$titleId",
                    "keyword":"$activity.keyword"
                },
                "votes":{
                    $sum:{
                        $cond:[
                            {
                                $eq:["$activity.vote",true]
                            },
                            1,
                            -1
                        ]
                    }
                }
            }
        },
        {
            $group:{
                "_id":"$_id.titleId",
                "titleId":{
                    $first:"$_id.titleId"
                },
                "activity":{
                    $push:{
                        "keyword":"$_id.keyword",
                        "votes":"$votes"
                    }
                }
            }
        },
        {
            $project:{
                "_id":0
            }
        }
    ]).pretty()
    

    输出:

    {
        "titleId" : "111222",
        "activity" : [
            {
                "keyword" : "Road Trip",
                "votes" : -1
            },
            {
                "keyword" : "Adventure",
                "votes" : 0
            },
            {
                "keyword" : "Friendship",
                "votes" : 1
            },
            {
                "keyword" : "Family Movie",
                "votes" : 1
            }
        ]
    }
    {
        "titleId" : "444222",
        "activity" : [
            {
                "keyword" : "Adventure",
                "votes" : -1
            },
            {
                "keyword" : "Sci Fi",
                "votes" : 1
            },
            {
                "keyword" : "Action",
                "votes" : -1
            },
            {
                "keyword" : "Educational film and videos",
                "votes" : 1
            },
            {
                "keyword" : "Space",
                "votes" : 1
            }
        ]
    }
    

    聚合阶段:

    • 第一阶段:展开“活动”数组。现在数组的每个元素都有一个文档
    • 第二阶段:根据标题ID和活动关键字进行分组 计算票数。 1 表示赞成,-1 表示反对。
    • 第三阶段:仅根据标题 ID 进行分组,并将所有活动合并到一个数组中
    • 第四阶段:从输出中消除不必要的字段

    【讨论】:

    • 非常感谢 MrS.Sharma,但有 1 个小问题。在上述解决方案中,对同一关键字的真票和假票将计数增加 1。我实际上需要假票以将计数减 1 - 例如,在标题 111222 的情况下,关键字道路trip 有 2 个假票和 1 个真票,这意味着总数应该是 -1。但是上面的解决方案给出了 2,因为它为 1 个真票和 1 个假票加上 1+1。最后的错误投票被排除了,因为该标题的第三个文档包含所有错误值,并且匹配语句将其过滤掉了。想法?
    • @raja 在查询中,只计算赞成票......但由于数据集错误,即使赞成票也能看到意外的输出。更新查询以减少downvote,以及更新的输出。谢谢:)
    猜你喜欢
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2022-01-11
    • 2020-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多