聚合操作允许用户处理多个文档并返回计算结果。
从效果而言,聚合框架相当于 SQL 查询中的GROUP BY、 LEFT OUTER JOIN 、 AS等。
整个聚合运算过程称为管道(Pipeline),由多个阶段(Stage)组成
原始数据集 -----------Stage---------》中间结果 ------------Stage--------》中间结果 --------------------》结果集
常用的聚合阶段运算符
#投影操作,将原始字段投影成指定名称,可以灵活控制输出文档的格式
db.books.aggregate([{$project:{name:"$title",_id:0,type:1,author:1}}])
#$match用于对文档进行筛选,尽可能将$match放在管道的前面位置,可以使用索引,过滤掉不需要的文档
db.books.aggregate([{$match:{type:"technology"}}])
#type:0导致的错误 Invalid $project :: caused by :: Cannot do exclusion on field type in inclusion projection
#$match和$project结合
db.books.aggregate([
{$match:{type:"technology"}},
{$project:{name:"$title",_id:0,type:1,author:{name:1}}}
])
#$count
db.books.aggregate([
{$match:{type:"technology"}},
{$count: "type_count"}
])
#$group
#accumulator操作符 $avg $first $last $max $min $push $addToSet $sum $stdDevPop $stdDevSamp
#book的数量,收藏总数和平均值
db.books.aggregate([
{$group:{_id:null,count:{$sum:1},pop:{$sum:"$favCount"},avg:{$avg:"$favCount"}}}
])
#统计每个作者的book收藏总数
db.books.aggregate([
{$group:{_id:"$author.name",pop:{$sum:"$favCount"}}}
])
#统计每个作者的每本book的收藏数
db.books.aggregate([
{$group:{_id:{name:"$author.name",title:"$title"},pop:{$sum:"$favCount"}}}
])
#每个作者的book的type合集
db.books.aggregate([
{$group:{_id:"$author.name",types:{$addToSet:"$type"}}}
])
#姓名为xx006的作者的book的tag数组拆分为多个文档
db.books.aggregate([
{$match:{"author.name":"xx006"}},
{$unwind:"$tag"}
])
#每个作者的book的tag合集
db.books.aggregate([
{$unwind:"$tag"},
{$group:{_id:"$author.name",types:{$addToSet:"$tag"}}}
])
# 使用includeArrayIndex选项来输出数组元素的数组索引
db.books.aggregate([
{$match:{"author.name":"fox"}},
{$unwind:{path:"$tag", includeArrayIndex: "arrayIndex"}}
])
# 使用preserveNullAndEmptyArrays选项在输出中包含缺少size字段,null或空数组的文档,防止漏掉文档
db.books.aggregate([
{$match:{"author.name":"fox"}},
{$unwind:{path:"$tag", preserveNullAndEmptyArrays: true}}
])
#$limit 限制传递到管道中下一阶段的文档数
db.books.aggregate([
{$limit : 5 }
])
#$skip 跳过进入stage的指定数量的文档,并将其余文档传递到管道中的下一个阶段
db.books.aggregate([
{$skip : 50 }
])
#$sort 对所有输入文档进行排序,并按排序顺序将它们返回到管道。
db.books.aggregate([
{$skip : 50 }
{$sort : {favCount:-1,"author.age":1}}
])
#$lookup 每个输入待处理的文档,经过$lookup 阶段的处理,输出的新文档中会包含一个新生成的数组
db.customer.aggregate([
{$lookup: {
from: "order",
localField: "customerCode",
foreignField: "customerCode",
as: "customerOrder"
}
}
])
db.order.aggregate([
{$lookup: {
from: "customer",
localField: "customerCode",
foreignField: "customerCode",
as: "curstomer"
}
},
{$lookup: {
from: "orderItem",
localField: "orderId",
foreignField: "orderId",
as: "orderItem"
}
}
])
#标签的热度排行,标签的热度则按其关联book文档的收藏数(favCount)来计算
db.books.aggregate([
{$match:{favCount:{$gt:0}}},
{$unwind:"$tag"},
{$group:{_id:"$tag",total:{$sum:"$favCount"}}},
{$sort:{total:-1}}
])
#$bucket
db.books.aggregate([{
$bucket:{
groupBy:"$favCount",
boundaries:[0,10,60,80,100],
default:"other",
output:{"count":{$sum:1}}
}
}])
#使用mongoimport工具导入数据
mongoimport -h 192.168.139.150 -d test -u lywtimer -p 0918 --authenticationDatabase=admin -c zips --file D:\mongodb-database-tools-windows-x86_64-100.9.0\zips.json
#返回人口超过1000万的州
db.zips.aggregate( [
{ $group: { _id: "$state", totalPop: { $sum: "$pop" } } },
{ $match: { totalPop: { $gte: 10*1000*1000 } } }
] )
MongoDB采用B+Tree 做索引,索引创建colletions上。
索引类型
索引属性
索引使用建议
# 创建单键索引
db.books.createIndex({title:1})
# 对内嵌文档字段创建索引:
db.books.createIndex({"author.name":1})
# 创建复合索引
db.books.createIndex({type:1,favCount:1})
#查看执行计划 winningPlan: {stage: 'COLLSCAN' winningPlan: {stage: 'FETCH'
db.books.find({type:"novel",favCount:{$gt:50}}).explain()
#查看索引信息
db.books.getIndexes()
#查看索引键
db.books.getIndexKeys()
#删除集合指定索引
db.col.dropIndex("索引名称")
#删除集合所有索引 不能删除主键索引
db.col.dropIndexes()
#创建 hash 索引
db.users.createIndex({username : 'hashed'})
#地理空间索引(2dsphereindex)就是专门用于实现位置检索的一种特殊索引
db.restaurant.createIndex({location : "2dsphere"})
#全文检索
db.reviews.createIndex( { comments: "text" } )
#通配符索引
db.products.createIndex( { "product_attributes.$**" : 1 } )
# 复合索引支持唯一性约束
db.values.createIndex({title:1,type:1},{unique:true})
#部分索引仅对满足指定过滤器表达式的文档进行索引
db.restaurants.createIndex(
{ cuisine: 1, name: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)
#不索引不包含xmpp_id字段的文档
db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )
# 创建 TTL 索引,TTL 值为3600秒
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
#创建隐藏索引
db.restaurants.createIndex({ borough: 1 },{ hidden: true });
# 隐藏现有索引
db.restaurants.hideIndex( { borough: 1} );
db.restaurants.hideIndex( "索引名称" )
# 取消隐藏索引
db.restaurants.unhideIndex( { borough: 1} );
db.restaurants.unhideIndex( "索引名称" );