MongoDB聚合操作2——聚合管道

2019-07-21  本文已影响0人  我是一名搬运工

MongoDB 中使用 db.COLLECTION_NAME.aggregate([{<stage>},...]) 方法来构建和使用聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。聚合管道的工作流程如下:

image

其中,$match$group 都是阶段操作符,而阶段 $group 中用到的 $sum 是表达式操作符。

1 阶段操作符

在下面的示例中我们会使用如下集合进行讲解:

>db.article.find().pretty()
{
    "_id" : ObjectId("5c088fec651e67152257d453"),
    "title" : "MongoDB Aggregate",
    "author" : "simon",
    "tags" : [
        "Mongodb",
        "Database",
        "Query"
    ],
    "pages" : 5.0,
    "time" : ISODate("2017-06-11T16:00:00.000Z")
},
{
    "_id" : ObjectId("5c088fec651e67152257d454"),
    "title" : "MongoDB Index",
    "author" : "simon",
    "tags" : [
        "Mongodb",
        "Index",
        "Query"
    ],
    "pages" : 3.0,
    "time" : ISODate("2018-11-11T16:00:00.000Z")
},
{
    "_id" : ObjectId("5c088fec651e67152257d455"),
    "title" : "MongoDB Query",
    "author" : "Aaron",
    "tags" : [
        "Mongodb",
        "Query"
    ],
    "pages" : 8.0,
    "time" : ISODate("2019-06-11T16:00:00.000Z")
}

1.1 $project

$project 用于修改输入文档的结构。可以用来重命名、增加或删除字段(域),也可以用于创建计算结果以及嵌套文档。
示例
返回的文档中只包含_idtages

>db.article.aggregate([{$project:{_id:1,tags:1}}])
{
    "_id" : ObjectId("5c088fec651e67152257d453"),
    "tags" : [
        "Mongodb",
        "Database",
        "Query"
    ]
},
{
    "_id" : ObjectId("5c088fec651e67152257d454"),
    "tags" : [
        "Mongodb",
        "Index",
        "Query"
    ]
},
{
    "_id" : ObjectId("5c088fec651e67152257d455"),
    "tags" : [
        "Mongodb",
        "Query"
    ]
}

新增字段

>db.article.aggregate([{$project:{_id:1,tags:1,editAuthor:'$author'}}])
{
    "_id" : ObjectId("5c088fec651e67152257d453"),
    "tags" : [
        "Mongodb",
        "Database",
        "Query"
    ],
    "editAuthor" : "simon"
},
{
    "_id" : ObjectId("5c088fec651e67152257d454"),
    "tags" : [
        "Mongodb",
        "Index",
        "Query"
    ],
    "editAuthor" : "simon"
},
{
    "_id" : ObjectId("5c088fec651e67152257d455"),
    "tags" : [
        "Mongodb",
        "Query"
    ],
    "editAuthor" : "Aaron"
}

1.2 $match

$match用于过滤数据,只输出符合条件的文档。
示例
查询出文档中 author 为 simon的数据

>db.article.aggregate([{$match:{author:'simon'}}])
{
    "_id" : ObjectId("5c088fec651e67152257d453"),
    "title" : "MongoDB Aggregate",
    "author" : "simon",
    "tags" : [
        "Mongodb",
        "Database",
        "Query"
    ],
    "pages" : 5.0,
    "time" : ISODate("2017-06-11T16:00:00.000Z")
},
{
    "_id" : ObjectId("5c088fec651e67152257d454"),
    "title" : "MongoDB Index",
    "author" : "simon",
    "tags" : [
        "Mongodb",
        "Index",
        "Query"
    ],
    "pages" : 3.0,
    "time" : ISODate("2018-11-11T16:00:00.000Z")
}

1.3 $group

$group用于将集合中的文档分组,可用于统计结果
示例
统计每个作者写的文章篇数

>db.article.aggregate([{$group:{_id:'$author',total:{$sum:1}}}])
{
    "_id" : "Aaron",
    "total" : 1.0
},
{
    "_id" : "simon",
    "total" : 2.0
}

1.4 $sort

对集合中的文档进行排序
示例
让集合按照页数进行升序排序

>db.article.aggregate([{$sort:{pages:1}}])
{
    "_id" : ObjectId("5c088fec651e67152257d454"),
    "title" : "MongoDB Index",
    "author" : "simon",
    "tags" : [
        "Mongodb",
        "Index",
        "Query"
    ],
    "pages" : 3.0,
    "time" : ISODate("2018-11-11T16:00:00.000Z")
},
{
    "_id" : ObjectId("5c088fec651e67152257d453"),
    "title" : "MongoDB Aggregate",
    "author" : "simon",
    "tags" : [
        "Mongodb",
        "Database",
        "Query"
    ],
    "pages" : 5.0,
    "time" : ISODate("2017-06-11T16:00:00.000Z")
},
{
    "_id" : ObjectId("5c088fec651e67152257d455"),
    "title" : "MongoDB Query",
    "author" : "Aaron",
    "tags" : [
        "Mongodb",
        "Query"
    ],
    "pages" : 8.0,
    "time" : ISODate("2019-06-11T16:00:00.000Z")
}

注意
如果以降序排列,则设置成 pages: -1

1.5 $unwind

将文档中数组类型的字段拆分成多条,每条文档包含数组中的一个值
示例
将集合中 tags字段进行拆分

>db.article.aggregate([{$match:{author:'Aaron'}},{$unwind:'$tags'}])
{
    "_id" : ObjectId("5c088fec651e67152257d455"),
    "title" : "MongoDB Query",
    "author" : "Aaron",
    "tags" : "Mongodb",
    "pages" : 8.0,
    "time" : ISODate("2019-06-11T16:00:00.000Z")
},
{
    "_id" : ObjectId("5c088fec651e67152257d455"),
    "title" : "MongoDB Query",
    "author" : "Aaron",
    "tags" : "Query",
    "pages" : 8.0,
    "time" : ISODate("2019-06-11T16:00:00.000Z")
}

注意

1.6 $limit

限制返回文档的数量
示例
返回集合的前一条文档

>db.article.aggregate([{$limit: 1}])
{
    "_id" : ObjectId("5c088fec651e67152257d453"),
    "title" : "MongoDB Aggregate",
    "author" : "simon",
    "tags" : [
        "Mongodb",
        "Database",
        "Query"
    ],
    "pages" : 5.0,
    "time" : ISODate("2017-06-11T16:00:00.000Z")
}

1.7 $skip

跳过指定数量的文档,并返回余下的文档
示例
跳过集合的前两个文档

>db.article.aggregate([{$skip: 2}])
{
    "_id" : ObjectId("5c088fec651e67152257d455"),
    "title" : "MongoDB Query",
    "author" : "Aaron",
    "tags" : [
        "Mongodb",
        "Query"
    ],
    "pages" : 8.0,
    "time" : ISODate("2019-06-11T16:00:00.000Z")
}

2表达式操作符

表达式操作符有很多操作类型,其中最常用的有布尔聚合操作、集合操作、比较聚合操作、算术聚合操作、字符串聚合操作、数组聚合操作、日期聚合操作、条件聚合操作、数据类型聚合操作等

2.1 布尔聚合操作

示例

>db.getCollection('col').find()
{
    "_id" : ObjectId("5c08c5b5651e67152257d45b"),
    "name" : "a",
    "classes" : "classe 1",
    "score" : 90.0
},
{
    "_id" : ObjectId("5c08c5b5651e67152257d45c"),
    "name" : "b",
    "classes" : "classe 2",
    "score" : 50.0
},
{
    "_id" : ObjectId("5c08c5b5651e67152257d45d"),
    "name" : "c",
    "classes" : "classe 3",
    "score" : 60.0
},
{
    "_id" : ObjectId("5c08c5b5651e67152257d45e"),
    "name" : "d",
    "classes" : "classe 4",
    "score" : 70.0
}

判断成绩是否大于80或者小于50

>db.col.aggregate(
   [
     {
       $project:
          {
            name: 1,
            score:1,  
            result: { $or: [ { $gt: [ "$score", 80 ] }, { $lt: [ "$score", 50 ] } ] }
          }
     }
   ]
)
{
    "_id" : ObjectId("5c08c5b5651e67152257d45b"),
    "name" : "a",
    "score" : 90.0,
    "result" : true
},
{
    "_id" : ObjectId("5c08c5b5651e67152257d45c"),
    "name" : "b",
    "score" : 50.0,
    "result" : false
},
{
    "_id" : ObjectId("5c08c5b5651e67152257d45d"),
    "name" : "c",
    "score" : 60.0,
    "result" : false
},
{
    "_id" : ObjectId("5c08c5b5651e67152257d45e"),
    "name" : "d",
    "score" : 70.0,
    "result" : false
}

2.2 集合操作

示例

>db.col.find()
{
    "_id" : ObjectId("5c08c98d651e67152257d45f"),
    "A" : [ 
        "java", 
        "phython", 
        "c++"
    ],
    "B" : [ 
        "java", 
        "phython", 
        "c++"
    ]
},
{
    "_id" : ObjectId("5c08c98d651e67152257d460"),
    "A" : [ 
        "java", 
        "c++"
    ],
    "B" : [ 
        "java", 
        "phython", 
        "c++"
    ]
},
{
    "_id" : ObjectId("5c08c98d651e67152257d461"),
    "A" : [ 
        "java", 
        "c++"
    ],
    "B" : []
}

计算A和B集合的

>db.col.aggregate(
   [
     { $project: { A:1, B: 1, union: { $setIntersection: [ "$A", "$B" ] }} }
   ]
)
{
    "_id" : ObjectId("5c08c98d651e67152257d45f"),
    "A" : [ 
        "java", 
        "phython", 
        "c++"
    ],
    "B" : [ 
        "java", 
        "phython", 
        "c++"
    ],
    "union" : [ 
        "c++", 
        "java", 
        "phython"
    ]
},
{
    "_id" : ObjectId("5c08c98d651e67152257d460"),
    "A" : [ 
        "java", 
        "c++"
    ],
    "B" : [ 
        "java", 
        "phython", 
        "c++"
    ],
    "union" : [ 
        "c++", 
        "java"
    ]
},
{
    "_id" : ObjectId("5c08c98d651e67152257d461"),
    "A" : [ 
        "java", 
        "c++"
    ],
    "B" : [],
    "union" : []
}

2.3 比较操作

示例

>db.col.find()
{
    "_id" : ObjectId("5c08cbb3651e67152257d463"),
    "score" : 80.0
}

score 大于等于 80

>db.col.aggregate(
[
    {$project:{_id:1,score:1,result:{$gte:['$score',80]}}}
]
)
{
    "_id" : ObjectId("5c08cbb3651e67152257d463"),
    "score" : 80.0,
    "result" : true
}

2.4 算数聚合操作

示例
score 加 10

db.col.aggregate(
[
    {$project:{_id:1,score:1,result:{$add:['$score',10]}}}
]
)
{
    "_id" : ObjectId("5c08cbb3651e67152257d463"),
    "score" : 80.0,
    "result" : 90.0
}

2.5 字符串聚合操作

示例

>db.col.find()
{
    "_id" : ObjectId("5c08cf2d651e67152257d464"),
    "name" : "abcdefgAAADccsD"
}

将 name 值大写

>db.col.aggregate([
   {
     $project: {name: 1,result:{$toUpper:'$name'}}
   }
])
{
    "_id" : ObjectId("5c08cf2d651e67152257d464"),
    "name" : "abcdefgAAADccsD",
    "result" : "ABCDEFGAAADCCSD"
}

2.6 数组聚合操作

示例

>db.col.find()
{
    "A" : [ 
        "java", 
        "phython", 
        "c++"
    ],
    "B" : [ 
        "java", 
        "phython", 
        "c++"
    ]
}

判断指定元素是否在数组中

db.col.aggregate([
   {
     $project: {A: 1,B:1,result:{$in:['java','$A']}}
   }
])
{
    "_id" : ObjectId("5c08c98d651e67152257d45f"),
    "A" : [ 
        "java", 
        "phython", 
        "c++"
    ],
    "B" : [ 
        "java", 
        "phython", 
        "c++"
    ],
    "result" : true
}

2.7 日期聚合操作

示例

>db.col.find()
{
    "_id" : ObjectId("5c08d61d651e67152257d465"),
    "date" : ISODate("2018-12-06T07:56:13.930Z")
}

日期聚合操作

>db.col.aggregate(
   [
     {
       $project:
         {
           year: { $year: "$date" },
           month: { $month: "$date" },
           day: { $dayOfMonth: "$date" },
           hour: { $hour: "$date" },
           minutes: { $minute: "$date" },
           seconds: { $second: "$date" },
           milliseconds: { $millisecond: "$date" },
           dayOfYear: { $dayOfYear: "$date" },
           dayOfWeek: { $dayOfWeek: "$date" },
           week: { $week: "$date" }
         }
     }
   ]
)
{
    "_id" : ObjectId("5c08d61d651e67152257d465"),
    "year" : 2018,
    "month" : 12,
    "day" : 6,
    "hour" : 7,
    "minutes" : 56,
    "seconds" : 13,
    "milliseconds" : 930,
    "dayOfYear" : 340,
    "dayOfWeek" : 5,
    "week" : 48
}

2.8 数据类型集合操作

示例

>db.col.aggregate(
   [
     {
       $project:
         {
           date:1,  
           type:{$type:'$date'}
         }
     }
   ]
)
{
    "_id" : ObjectId("5c08d61d651e67152257d465"),
    "date" : ISODate("2018-12-06T07:56:13.930Z"),
    "type" : "date"
}

3 聚合管道的优化与限制

3.1 优化

默认情况下,在整个集合作为聚合管道的输入情况下,为了提高处理数据的效率,可以使用一下策略:

当聚合管道执行命令时,MongoDB 也会对各个阶段自动进行优化,主要包括以下几个情况:

3.2 限制

链接:https://www.jianshu.com/p/f1d4300c0067
来源:简书

上一篇 下一篇

猜你喜欢

热点阅读