mongodb中的多个组

时间:2016-08-02 07:39:53

标签: mongodb mongodb-query aggregation-framework

我的收藏看起来像这样。

{
"_id" : ObjectId("572c4ed33c1b5f51215219a8"),

"name" : "This is an angular course, and integeration with php",
"description" : "After we connected we can query or update the database just how we would using the mongo API with the exception that we use a callback. The format for callbacks is always callback(error, value) where error is null if no exception has occured. The update methods save, remove, update and findAndModify also pass the lastErrorObject as the last argument to the callback function.",
"difficulty_level" : "Beginner",
"type" : "Fast Track",
"tagged_skills" : [ 
    {
        "_id" : "5714e894e09a0f7d804b2254",
        "name" : "PHP"
    }, 
    {
        "_id" : "5717355806313b1f1715fa50",
        "name" : "c++"
    }, 
    {
        "_id" : "5715025bc2c5dbb4675180da",
        "name" : "java"
    }, 
    {
        "_id" : "5714f188ec325f5359979e33",
        "name" : "symphony"
    }
]}

我希望根据类型,难度级别和标记技能对该集合进行分组,并在单个查询中获取计数。

我无法增加技能数量。

我的查询如下: -

db.course.aggregate([
{$unwind:"$tagged_skills"},
{$group:{
    _id:null,
skills: { $addToSet: "$tagged_skills.name" },
Normal_df:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$difficulty_level","Normal"] },
                    1,
                    0
                ]
            }},
Beginner_df:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$difficulty_level","Beginner"] },
                    1,
                    0
                ]
            }},
Intermediate_df:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$difficulty_level","Intermediate"] },
                    1,
                    0
                ]
            }},
Advanced_df:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$difficulty_level","Advanced"] },
                    1,
                    0
                ]
            }},
Fast_Track_type:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$type","Fast Track"] },
                    1,
                    0
                ]
            }},
Normal_type:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$type","Normal"] },
                    1,
                    0
                ]
            }},
Beginner_type:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$type","Beginner"] },
                    1,
                    0
                ]
            }},
Normal_Track_type:{$sum:{ 
                "$cond": [
                    { "$eq":[ "$type","Normal Track"] },
                    1,
                    0
                ]
            }},
    }}
])

结果如下: -

{
    "_id" : null,

    "skills" : [ 
        "SQL", 
        "PHP", 
        "java", 
        "Angular Js", 
        "Laravel 23", 
        "c++", 
        "Node Js", 
        "symphony", 
        "Mysql", 
        "Express Js", 
        "JAVA"
    ],
    "Normal_df" : 1,
    "Beginner_df" : 14,
    "Intermediate_df" : 7,
    "Advanced_df" : 2,
    "Fast_Track_type" : 8,
    "Normal_type" : 6,
    "Beginner_type" : 1,
    "Normal_Track_type" : 9
}

我也希望获得所有技能。

1 个答案:

答案 0 :(得分:2)

要获得所有技能,您需要先获得所有技能的列表。您可以在approapriate字段上运行 distinct 命令来获取此列表。使用此列表,您可以构建相应的 $group 管道文档,该文档将使用 $sum $cond 运营商。

考虑以下用例:

var difficultyLevels = db.course.distinct("difficulty_level"),
    types = db.course.distinct("type"),
    skills = db.course.distinct("tagged_skills.name"),
    unwindOperator = { "$unwind": "$tagged_skills" },
    groupOperator = { 
        "$group": { 
            "_id": null,
            "skills": { "$addToSet": "$tagged_skills.name" }
        }       
    };

difficultyLevels.forEach(function (df){ 
    groupOperator["$group"][df+"_df"] = { 
       "$sum": { 
           "$cond": [ { "$eq": ["$difficulty_level",  df] }, 1, 0] 
       }
   }
});

types.forEach(function (type){ 
    groupOperator["$group"][type.replace(" ", "_")+"_type"] = { 
       "$sum": { 
           "$cond": [ { "$eq": ["$type",  type] }, 1, 0] 
       }
   }
});

skills.forEach(function (skill){ 
    groupOperator["$group"][skill] = { 
       "$sum": { 
           "$cond": [ { "$eq": ["$tagged_skills.name",  skill] }, 1, 0] 
       }
   }
});

//printjson(groupOperator);
db.course.aggregate([unwindOperator, groupOperator]);

在第一行中,我们通过在difficulty_level字段上运行 distinct 命令获得具有难度级别的数组

db.course.distinct("difficulty_level")

这将生成数组

var difficultyLevels = ["Normal", "Beginner", "Intermediate", "Advanced"]

同样,前面的 distinct 操作将返回该密钥的可能唯一值列表。

获取这些列表后,您可以使用 forEach() 方法创建管道对象,以填充列表中每个给定项目的文档键。然后,您可以使用生成的文档,该文档将如下所示

printjson(groupOperator);
{
    "$group" : {
        "_id" : null,
        "skills" : {
            "$addToSet" : "$tagged_skills.name"
        },
        "Beginner_df" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$difficulty_level",
                            "Beginner"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "Intermediate_df" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$difficulty_level",
                            "Intermediate"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "Fast_Track_type" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$type",
                            "Fast Track"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "PHP" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$tagged_skills.name",
                            "PHP"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "c++" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$tagged_skills.name",
                            "c++"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "java" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$tagged_skills.name",
                            "java"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "symphony" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$tagged_skills.name",
                            "symphony"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "C#" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$tagged_skills.name",
                            "C#"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "Scala" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$tagged_skills.name",
                            "Scala"
                        ]
                    },
                    1,
                    0
                ]
            }
        },
        "javascript" : {
            "$sum" : {
                "$cond" : [
                    {
                        "$eq" : [
                            "$tagged_skills.name",
                            "javascript"
                        ]
                    },
                    1,
                    0
                ]
            }
        }
    }
}