mongo 使用聚合合并字段

Posted wzs5800

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongo 使用聚合合并字段相关的知识,希望对你有一定的参考价值。

需求

有时候,我们需要在查询结果中将某个字段(数组)合并起来,返回一个数组即可。

例子

描述

假设我集合中中有以下字段:

技术图片

 ps: experiences[]保存阅历,阅历里每组由职业、技能组成(只作举例用)。

{ 
    "_id" : ObjectId("5eb6bb5bc95fdd10d0f6d21e"), 
    "name" : "小明", 
    "education" : "本科", 
    "experiences" : [
        {
            "profession" : "程序员", 
            "ability" : [
                "java", 
                "nodejs", 
                "golang"
            ]
        }
    ]
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5eb6bbdbc95fdd10d0f6d220"), 
    "name" : "小红", 
    "education" : "本科", 
    "experiences" : [
        {
            "profession" : "销售", 
            "ability" : [
                "沟通", 
                "财务计算"
            ]
        }, 
        {
            "profession" : "采购员", 
            "ability" : [
                "英语", 
                "统计"
            ]
        }
    ]
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5eb6bdbbc95fdd10d0f6d23f"), 
    "name" : "小三", 
    "education" : "大专", 
    "experiences" : [
        {
            "profession" : "行政助理", 
            "ability" : [
                "英语"
            ]
        }
    ]
}

接下来我想查询出所有学历为“本科”的阅历(experiences)列表,并把它们合并成一个数组返回,如:

{ 
    "_id" : "1", 
    "experiences" : [
        { "profession" : "销售", "ability" : ["沟通", "财务计算"] }, 
        { "profession" : "采购员", "ability" : ["英语",  "统计"]}, 
        { "profession" : "程序员", "ability" : ["java", "nodejs", "golang"]}
    ]
}

实现

使用Aggregate来实现。

db.getCollection("user").aggregate(
    [
        { 
            "$match" : { "education" : "本科" }
        }, 
        { 
            "$group" : {
                "_id" : "1", 
                "experiences" : {
                    "$addToSet" : "$experiences"
                }
            }
        }, 
        { 
            "$project" : {
                "experiences" : {
                    "$reduce" : {
                        "input" : "$experiences", 
                        "initialValue" : [], 
                        "in" : { "$concatArrays" : ["$$value", "$$this"] }
                    }
                }
            }
        }
    ]
);

说明

$match: 选择器,筛选的条件,这里查询出学历(education)为本科的数据。

{ "$match" : { "education" : "本科" } }

$group: 相当于sql中的group by, 例子中的"_id"只是用于分组的标识,“experiences“设置分组返回到哪个字段上,相当于as。

{ 
    "$group" : {
         "_id" : "1", 
         "experiences" : {
             "$addToSet" : "$experiences"
         }
    }
}

到这里,会把学历为“本科”的阅历全部查出来,数据是这样子:

{ 
    "_id" : "1", 
    "experiences" : [
        [
            {"profession" : "销售",  "ability" : [ "沟通",  "财务计算" ]}, 
            {"profession" : "采购员", "ability" : [ "英语",  "统计" ]}
        ], 
        [
            {"profession" : "程序员",  "ability" : ["java", "nodejs", "golang"]}
        ]
    ]
}

但还不是我们要的结果,因为这个需要在代码额外遍历一次,所以我们在处理一下。

$project: 接受一个文档,该文档可以指定包含字段、禁止显示id字段、添加新字段以及重置现有字段的值。或者,可以指定排除字段。

{ 
    "$project" : {
        "experiences" : {
            "$reduce" : {
                "input" : "$experiences", 
                "initialValue" : [],
                "in" : { "$concatArrays" : ["$$value", "$$this"] }
            }
        }
    }
}  

$reduce的作用就是将"in"里的表达式应用到"input"数组里,并将它们合并成一个数组。

"in"里面的表达式可以很灵活的对数组操作,这里用的$concatArrays将experiences[]字段里的元素连接起来。

更多可以查看官方文档:https://docs.mongodb.com/manual/reference/operator/aggregation/reduce/

 

(完)

 

以上是关于mongo 使用聚合合并字段的主要内容,如果未能解决你的问题,请参考以下文章

C ++写入mongo,字符串字段在聚合管道中不起作用

管道阶段规范对象必须包含一个带有 php mongo 聚合的字段

管道阶段规范对象必须包含一个带有 php mongo 聚合的字段

是否可以在 mongo 的组聚合后重命名 _id 字段?

基于键合并两个数组并使用 mongodb 聚合添加新字段

mongo聚合函数count问题