在之前的两篇博文《MongoDB基础之原生方法增删改查》和《MongoDB基础之查询表达式》中,介绍了 MongoDB 的基本查询功能,这篇博文我们来介绍一个比较复杂的场景,也就是聚合查询。

3.1 测试数据录入

db.post.insert([
    {id:1, title:'PHP从入门到精通', author:'张无忌', category_id:1, tags:['php','后端'], hits:20, created_at:ISODate('2019-03-01 10:20:32')},
    {id:2, title:'Linux从学童到出家', author:'张翠山', category_id:1, tags:['linux','服务器'], hits:234, created_at:ISODate('2019-03-12 16:22:50')},
    {id:3, title:'MySQL从删库到跑路', author:'张三丰', category_id:2, tags:['mysql','database','数据库'], hits:73, created_at:ISODate('2019-04-01 19:43:20')},
    {id:4, title:'利用Python求心理阴影面积', author:'张无忌', category_id:1, tags:['python','后端'], hits:30, created_at:ISODate('2019-04-23 16:20:09')},
    {id:5, title:'Java从基础到脸黑', author:'殷素素', category_id:1, tags:['java','后端','性能'], hits:145, created_at:ISODate('2019-05-01 11:43:22')},
    {id:6, title:'Mongodb从幼儿园到博士后', author:'赵敏', category_id:2, tags:['mongodb','database','query','数据库'], hits:76, created_at:ISODate('2019-05-01 16:11:07')},
    {id:7, title:'用Nodejs来填补心灵空白', author:'张翠山', category_id:3, tags:['nodejs','前端','后端'], hits:203, created_at:ISODate('2019-05-02 18:34:23')},
    {id:8, title:'沉迷C++无法自拔', author:'张无忌', category_id:1, tags:['c++','后端','服务器'], hits:54, created_at:ISODate('2019-05-06 13:54:23')},
    {id:9, title:'Swift脱单指南', author:'张无忌', category_id:3, tags:['swift','前端'], hits:183, created_at:ISODate('2019-05-10 10:21:12')}
    {id:10, title:'Swift脱单指南', author:'宋青书', category_id:3, tags:['swift','前端'], hits:42, created_at:ISODate('2019-05-18 21:32:54')}
]);
db.category.insert([
    {id:1, name:'后端编程语言'},
    {id:2, name:'数据库'},
    {id:3, name:'前端编程语言'}
]);

3.2 管道

$project

db.post.aggregate([
    {$project:{title:1, author:1}}
])
db.post.aggregate([
    {$project:{title:1, writer:'$author'}}
])

3.2.2 $match

db.post.aggregate([
    {$match:{category_id:2}}
])
db.post.aggregate([
    {$match:{hits:{$gt:100}}}
])

3.2.3 $group

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        total:{$sum:1}
    }}
])
db.post.aggregate([
    {$project:{
        y_m:{$dateToString:{format:"%Y-%m", date:"$created_at"}}
    }},
    {$group:{
        _id:'$y_m',
        total:{$sum:1}
    }}
])

3.2.4 $sort

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        total:{$sum:1}
    }},
    {$sort:{total:-1}}
])

3.2.5 $limit

db.post.aggregate([
    {$sort:{hits:-1}},
    {$limit:1}
])

3.2.6 $skip

db.post.aggregate([
    {$sort:{hits:-1}},
    {$skip:2},
    {$limit:2}
])

3.2.7 $unwind

db.post.aggregate([
    {$match:{id:3}},
    {$unwind:'$tags'}
])

3.2.8 $lookup

db.post.aggregate([
    {
        $lookup:{
            from:'category',
            localField:'category_id',
            foreignField:'id',
            as:'category_info'
        }
    }
])

3.3 聚合表达式

3.3.1 $sum

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        hits_total:{$sum:'$hits'}
    }}
])

3.3.2 $avg

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        hits_avg:{$avg:'$hits'}
    }}
])

3.3.3 $min

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        hits_min:{$avg:'$hits'}
    }}
])

3.3.4 $max

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        hits_max:{$max:'$hits'}
    }}
])

3.3.5 $push

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        title_arr:{$push:'$title'}
    }}
])

3.3.6 $addToSet

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        title_arr:{$addToSet:'$title'}
    }}
])

3.3.7 $first

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        title_first:{$first:'$title'}
    }}
])

3.3.8 $last

db.post.aggregate([
    {$group:{
        _id:'$category_id',
        title_last:{$last:'$title'}
    }}
])

本文为 陈华 原创,欢迎转载,但请注明出处:http://www.ichenhua.cn/read/40