博客网址:www.shicoder.top
微信:kj11011029
欢迎加群聊天 :452380935
上一次我们对mongodb的一些简单命令进行讲解,这一次我们来看下mongodb的高级操作吧
聚合操作
所谓聚合操作,就是类似mysql中的where
、order by
等一些操作,MongoDB 的聚合框架就是将文档输入处理管道(pipeline),在管道内完成对文档的操作(包括多个stage)
db.集合.aggregate(
[
{stage1},
{stage2},
...
]
{option}
);
主要有以下几个阶段
- $match用于过滤数据,用于聚合阶段的输入
- $order用指定的键,对文档进行排序
- $limit用于限制多少个文档作为输入
- $skip跳过多少个文档
- $project投影字段,可以理解为查询多少个字段,类似为 select a,b,c 中的 a,b,c
- $group进行分组操作,其中_id字段用于指定需要分组的字段。
- $count返回这个聚合管道阶段的文档的数量
数据准备
首先为了后续的案例分析,我们先准备一些数据
var tags = ["nosql","mongodb","document","developer","popular"];
var types = ["technology","sociality","travel","novel","literature"];
var books=[];
for(var i=0;i<50;i++){
var typeIdx = Math.floor(Math.random()*types.length);
var tagIdx = Math.floor(Math.random()*tags.length);
var tagIdx2 = Math.floor(Math.random()*tags.length);
var favCount = Math.floor(Math.random()*100);
var username = "xx00"+Math.floor(Math.random()*10);
var age = 20 + Math.floor(Math.random()*15);
var book = {
title: "book-"+i,
type: types[typeIdx],
tag: [tags[tagIdx],tags[tagIdx2]],
favCount: favCount,
author: {name:username,age:age}
};
books.push(book)
}
db.books.insertMany(books);
> use book
switched to db book
> load("book.js")
true
$match
$match用于对文档进行筛选,之后可以在得到的文档子集上做聚合,$match可以使用除了地理空间之 外的所有常规查询操作符,在实际应用中尽可能将\$match放在管道的前面位置。这样有两个好处:一是 可以快速将不需要的文档过滤掉,以减少管道的工作量;二是如果再投射和分组之前执行$match,查询 可以使用索引
比如查询type
为technology
的书籍
db.books.aggregate([{$match:{type:"technology"}}])
{ "_id" : ObjectId("6271102510f566b3b1a8dba5"), "title" : "book-0", "type" : "technology", "tag" : [ "mongodb", "developer" ], "favCount" : 72, "author" : { "name" : "xx002", "age" : 26 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb0"), "title" : "book-11", "type" : "technology", "tag" : [ "popular", "nosql" ], "favCount" : 61, "author" : { "name" : "xx000", "age" : 32 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb5"), "title" : "book-16", "type" : "technology", "tag" : [ "document", "developer" ], "favCount" : 50, "author" : { "name" : "xx000", "age" : 32 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb9"), "title" : "book-20", "type" : "technology", "tag" : [ "document", "developer" ], "favCount" : 42, "author" : { "name" : "xx007", "age" : 20 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbbc"), "title" : "book-23", "type" : "technology", "tag" : [ "mongodb", "popular" ], "favCount" : 4, "author" : { "name" : "xx005", "age" : 21 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbbd"), "title" : "book-24", "type" : "technology", "tag" : [ "developer", "mongodb" ], "favCount" : 1, "author" : { "name" : "xx007", "age" : 29 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbc7"), "title" : "book-34", "type" : "technology", "tag" : [ "developer", "document" ], "favCount" : 80, "author" : { "name" : "xx001", "age" : 20 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbcc"), "title" : "book-39", "type" : "technology", "tag" : [ "document", "document" ], "favCount" : 48, "author" : { "name" : "xx009", "age" : 25 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbcd"), "title" : "book-40", "type" : "technology", "tag" : [ "developer", "document" ], "favCount" : 63, "author" : { "name" : "xx000", "age" : 25 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbce"), "title" : "book-41", "type" : "technology", "tag" : [ "popular", "developer" ], "favCount" : 29, "author" : { "name" : "xx007", "age" : 27 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbd1"), "title" : "book-44", "type" : "technology", "tag" : [ "document", "mongodb" ], "favCount" : 64, "author" : { "name" : "xx007", "age" : 31 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbd6"), "title" : "book-49", "type" : "technology", "tag" : [ "mongodb", "nosql" ], "favCount" : 35, "author" : { "name" : "xx009", "age" : 24 } }
$count
计数并返回与查询匹配的结果数
db.books.aggregate([ {$match:{type:"technology"}}, {$count: "type_count"}
])
$match阶段筛选出type匹配technology的文档,并传到下一阶段;
$count阶段返回聚合管道中剩余文档的计数,并将该值分配给type_count
{ "type_count" : 12 }
$group
按指定的表达式对文档进行分组,并将每个不同分组的文档输出到下一个阶段。输出文档包含一个\_id字 段,该字段按键包含不同的组。 输出文档还可以包含计算字段,该字段保存由$group的\_id字段分组的一些accumulator表达式的值。 $group不会输出具体的文档而只是统计信息
{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ...
} }
查询book的数量、收藏总数和平均值
db.books.aggregate([
{$group:{_id:null,count:{$sum:1},pop:{$sum:"$favCount"},avg:{$avg:"$favCount"}}}
])
{ "_id" : null, "count" : 50, "pop" : 2452, "avg" : 49.04 }
统计每个作者的book收藏总数
db.books.aggregate([
{$group:{_id:"$author.name",pop:{$sum:"$favCount"}}}
])
{ "_id" : "xx001", "pop" : 176 }
{ "_id" : "xx006", "pop" : 90 }
{ "_id" : "xx000", "pop" : 531 }
{ "_id" : "xx007", "pop" : 213 }
{ "_id" : "xx008", "pop" : 193 }
{ "_id" : "xx005", "pop" : 353 }
{ "_id" : "xx009", "pop" : 175 }
{ "_id" : "xx003", "pop" : 302 }
{ "_id" : "xx004", "pop" : 200 }
{ "_id" : "xx002", "pop" : 219 }
统计每个作者的每本book的收藏数
db.books.aggregate([
{$group:{_id:{name:"$author.name",title:"$title"},pop:{$sum:"$favCount"}}}
])
{ "_id" : { "name" : "xx008", "title" : "book-48" }, "pop" : 16 }
{ "_id" : { "name" : "xx000", "title" : "book-46" }, "pop" : 31 }
{ "_id" : { "name" : "xx007", "title" : "book-44" }, "pop" : 64 }
{ "_id" : { "name" : "xx003", "title" : "book-43" }, "pop" : 30 }
{ "_id" : { "name" : "xx003", "title" : "book-42" }, "pop" : 65 }
{ "_id" : { "name" : "xx007", "title" : "book-41" }, "pop" : 29 }
{ "_id" : { "name" : "xx004", "title" : "book-38" }, "pop" : 51 }
{ "_id" : { "name" : "xx001", "title" : "book-36" }, "pop" : 66 }
{ "_id" : { "name" : "xx000", "title" : "book-47" }, "pop" : 96 }
{ "_id" : { "name" : "xx001", "title" : "book-34" }, "pop" : 80 }
{ "_id" : { "name" : "xx008", "title" : "book-33" }, "pop" : 75 }
{ "_id" : { "name" : "xx005", "title" : "book-32" }, "pop" : 76 }
{ "_id" : { "name" : "xx009", "title" : "book-49" }, "pop" : 35 }
{ "_id" : { "name" : "xx003", "title" : "book-30" }, "pop" : 9 }
{ "_id" : { "name" : "xx003", "title" : "book-28" }, "pop" : 76 }
{ "_id" : { "name" : "xx000", "title" : "book-25" }, "pop" : 37 }
{ "_id" : { "name" : "xx007", "title" : "book-24" }, "pop" : 1 }
{ "_id" : { "name" : "xx002", "title" : "book-45" }, "pop" : 86 }
{ "_id" : { "name" : "xx005", "title" : "book-23" }, "pop" : 4 }
{ "_id" : { "name" : "xx005", "title" : "book-21" }, "pop" : 84 }
$project
投影操作, 将原始字段投影成指定名称, 如将集合中的 title 投影成 name
db.books.aggregate([{$project:{name:"$title"}}])
{ "_id" : ObjectId("6271102510f566b3b1a8dba5"), "name" : "book-0" }
{ "_id" : ObjectId("6271102510f566b3b1a8dba6"), "name" : "book-1" }
{ "_id" : ObjectId("6271102510f566b3b1a8dba7"), "name" : "book-2" }
{ "_id" : ObjectId("6271102510f566b3b1a8dba8"), "name" : "book-3" }
{ "_id" : ObjectId("6271102510f566b3b1a8dba9"), "name" : "book-4" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbaa"), "name" : "book-5" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbab"), "name" : "book-6" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbac"), "name" : "book-7" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbad"), "name" : "book-8" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbae"), "name" : "book-9" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbaf"), "name" : "book-10" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb0"), "name" : "book-11" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb1"), "name" : "book-12" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb2"), "name" : "book-13" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb3"), "name" : "book-14" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb4"), "name" : "book-15" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb5"), "name" : "book-16" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb6"), "name" : "book-17" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb7"), "name" : "book-18" }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb8"), "name" : "book-19" }
$project 可以灵活控制输出文档的格式,也可以剔除不需要的字段
db.books.aggregate([{$project:{name:"$title",_id:0,type:1,author:1}}])
{ "type" : "technology", "author" : { "name" : "xx002", "age" : 26 }, "name" : "book-0" }
{ "type" : "travel", "author" : { "name" : "xx003", "age" : 26 }, "name" : "book-1" }
{ "type" : "novel", "author" : { "name" : "xx002", "age" : 30 }, "name" : "book-2" }
{ "type" : "sociality", "author" : { "name" : "xx009", "age" : 31 }, "name" : "book-3" }
{ "type" : "literature", "author" : { "name" : "xx004", "age" : 27 }, "name" : "book-4" }
{ "type" : "novel", "author" : { "name" : "xx008", "age" : 26 }, "name" : "book-5" }
{ "type" : "literature", "author" : { "name" : "xx002", "age" : 29 }, "name" : "book-6" }
{ "type" : "novel", "author" : { "name" : "xx007", "age" : 24 }, "name" : "book-7" }
{ "type" : "sociality", "author" : { "name" : "xx005", "age" : 32 }, "name" : "book-8" }
{ "type" : "novel", "author" : { "name" : "xx005", "age" : 31 }, "name" : "book-9" }
{ "type" : "literature", "author" : { "name" : "xx000", "age" : 27 }, "name" : "book-10" }
{ "type" : "technology", "author" : { "name" : "xx000", "age" : 32 }, "name" : "book-11" }
{ "type" : "novel", "author" : { "name" : "xx003", "age" : 23 }, "name" : "book-12" }
{ "type" : "travel", "author" : { "name" : "xx006", "age" : 29 }, "name" : "book-13" }
{ "type" : "novel", "author" : { "name" : "xx004", "age" : 25 }, "name" : "book-14" }
{ "type" : "literature", "author" : { "name" : "xx005", "age" : 34 }, "name" : "book-15" }
{ "type" : "technology", "author" : { "name" : "xx000", "age" : 32 }, "name" : "book-16" }
{ "type" : "novel", "author" : { "name" : "xx003", "age" : 33 }, "name" : "book-17" }
{ "type" : "novel", "author" : { "name" : "xx001", "age" : 24 }, "name" : "book-18" }
{ "type" : "travel", "author" : { "name" : "xx004", "age" : 27 }, "name" : "book-19" }
从嵌套文档中排除字段
比如想从author中只看name
db.books.aggregate([
{$project:{name:"$title",_id:0,type:1,"author.name":1}}
])
或者
db.books.aggregate([
{$project:{name:"$title",_id:0,type:1,author:{name:1}}}
])
$limit
限制传递到管道中下一阶段的文档数
如仅返回管道传递给它的前5个文档
db.books.aggregate([
{$limit : 5 }
])
{ "_id" : ObjectId("6271102510f566b3b1a8dba5"), "title" : "book-0", "type" : "technology", "tag" : [ "mongodb", "developer" ], "favCount" : 72, "author" : { "name" : "xx002", "age" : 26 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dba6"), "title" : "book-1", "type" : "travel", "tag" : [ "mongodb", "document" ], "favCount" : 20, "author" : { "name" : "xx003", "age" : 26 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dba7"), "title" : "book-2", "type" : "novel", "tag" : [ "nosql", "mongodb" ], "favCount" : 6, "author" : { "name" : "xx002", "age" : 30 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dba8"), "title" : "book-3", "type" : "sociality", "tag" : [ "popular", "nosql" ], "favCount" : 92, "author" : { "name" : "xx009", "age" : 31 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dba9"), "title" : "book-4", "type" : "literature", "tag" : [ "document", "mongodb" ], "favCount" : 10, "author" : { "name" : "xx004", "age" : 27 } }
$skip
跳过进入stage的指定数量的文档,并将其余文档传递到管道中的下一个阶段
如跳过管道传递给它的前5个文档
db.books.aggregate([
{$skip : 5 }
])
{ "_id" : ObjectId("6271102510f566b3b1a8dbaa"), "title" : "book-5", "type" : "novel", "tag" : [ "developer", "nosql" ], "favCount" : 67, "author" : { "name" : "xx008", "age" : 26 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbab"), "title" : "book-6", "type" : "literature", "tag" : [ "mongodb", "developer" ], "favCount" : 55, "author" : { "name" : "xx002", "age" : 29 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbac"), "title" : "book-7", "type" : "novel", "tag" : [ "mongodb", "developer" ], "favCount" : 24, "author" : { "name" : "xx007", "age" : 24 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbad"), "title" : "book-8", "type" : "sociality", "tag" : [ "popular", "nosql" ], "favCount" : 70, "author" : { "name" : "xx005", "age" : 32 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbae"), "title" : "book-9", "type" : "novel", "tag" : [ "nosql", "nosql" ], "favCount" : 32, "author" : { "name" : "xx005", "age" : 31 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbaf"), "title" : "book-10", "type" : "literature", "tag" : [ "developer", "nosql" ], "favCount" : 99, "author" : { "name" : "xx000", "age" : 27 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb0"), "title" : "book-11", "type" : "technology", "tag" : [ "popular", "nosql" ], "favCount" : 61, "author" : { "name" : "xx000", "age" : 32 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb1"), "title" : "book-12", "type" : "novel", "tag" : [ "popular", "nosql" ], "favCount" : 51, "author" : { "name" : "xx003", "age" : 23 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb2"), "title" : "book-13", "type" : "travel", "tag" : [ "developer", "popular" ], "favCount" : 3, "author" : { "name" : "xx006", "age" : 29 } }
$sort
对所有输入文档进行排序,并按排序顺序将它们返回到管道
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
要对字段进行排序,请将排序顺序设置为1或-1,以分别指定升序或降序排序,如下例所示
db.books.aggregate([
{$sort : {favCount:-1,title:1}}
])
{ "_id" : ObjectId("6271102510f566b3b1a8dbaf"), "title" : "book-10", "type" : "literature", "tag" : [ "developer", "nosql" ], "favCount" : 99, "author" : { "name" : "xx000", "age" : 27 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbd4"), "title" : "book-47", "type" : "literature", "tag" : [ "popular", "developer" ], "favCount" : 96, "author" : { "name" : "xx000", "age" : 24 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dba8"), "title" : "book-3", "type" : "sociality", "tag" : [ "popular", "nosql" ], "favCount" : 92, "author" : { "name" : "xx009", "age" : 31 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb4"), "title" : "book-15", "type" : "literature", "tag" : [ "nosql", "mongodb" ], "favCount" : 87, "author" : { "name" : "xx005", "age" : 34 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbc2"), "title" : "book-29", "type" : "sociality", "tag" : [ "nosql", "developer" ], "favCount" : 87, "author" : { "name" : "xx006", "age" : 21 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbd2"), "title" : "book-45", "type" : "sociality", "tag" : [ "mongodb", "popular" ], "favCount" : 86, "author" : { "name" : "xx002", "age" : 23 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbba"), "title" : "book-21", "type" : "sociality", "tag" : [ "popular", "developer" ], "favCount" : 84, "author" : { "name" : "xx005", "age" : 27 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbca"), "title" : "book-37", "type" : "literature", "tag" : [ "developer", "popular" ], "favCount" : 83, "author" : { "name" : "xx000", "age" : 23 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbc7"), "title" : "book-34", "type" : "technology", "tag" : [ "developer", "document" ], "favCount" : 80, "author" : { "name" : "xx001", "age" : 20 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbc1"), "title" : "book-28", "type" : "novel", "tag" : [ "developer", "document" ], "favCount" : 76, "author" : { "name" : "xx003", "age" : 25 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbc5"), "title" : "book-32", "type" : "sociality", "tag" : [ "mongodb", "document" ], "favCount" : 76, "author" : { "name" : "xx005", "age" : 30 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbc6"), "title" : "book-33", "type" : "novel", "tag" : [ "document", "developer" ], "favCount" : 75, "author" : { "name" : "xx008", "age" : 29 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dba5"), "title" : "book-0", "type" : "technology", "tag" : [ "mongodb", "developer" ], "favCount" : 72, "author" : { "name" : "xx002", "age" : 26 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbad"), "title" : "book-8", "type" : "sociality", "tag" : [ "popular", "nosql" ], "favCount" : 70, "author" : { "name" : "xx005", "age" : 32 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbaa"), "title" : "book-5", "type" : "novel", "tag" : [ "developer", "nosql" ], "favCount" : 67, "author" : { "name" : "xx008", "age" : 26 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbc9"), "title" : "book-36", "type" : "literature", "tag" : [ "nosql", "popular" ], "favCount" : 66, "author" : { "name" : "xx001", "age" : 21 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbcf"), "title" : "book-42", "type" : "literature", "tag" : [ "document", "nosql" ], "favCount" : 65, "author" : { "name" : "xx003", "age" : 29 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbd1"), "title" : "book-44", "type" : "technology", "tag" : [ "document", "mongodb" ], "favCount" : 64, "author" : { "name" : "xx007", "age" : 31 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbcd"), "title" : "book-40", "type" : "technology", "tag" : [ "developer", "document" ], "favCount" : 63, "author" : { "name" : "xx000", "age" : 25 } }
{ "_id" : ObjectId("6271102510f566b3b1a8dbb0"), "title" : "book-11", "type" : "technology", "tag" : [ "popular", "nosql" ], "favCount" : 61, "author" : { "name" : "xx000", "age" : 32 } }
评论 (0)