MongoDB 聚合操作

说名:本篇文章开始介绍 aggregate(聚合函数)、count() 合计、distinct(去除重复)、$sum(求和操作)、"$unwind""$out" 等操作。

MongoDB 聚合操作

MongoDB 中聚合(aggregate) 主要用于处理数据(诸如统计平均值、求和等),并返回计算后的数据结果。

前提说明

在使用 RoboMongo 的时候发现获取集合有一种新的方式(两种都是可以使用的):

// 老版本的写法
db.collection.find();

// 新版本中支持(使用 getCollection 函数获取到集合)
db.getCollection('collectionName').find({});

简介 aggregate

官网地址:https://docs.mongodb.com/manual/aggregation

"count()"

函数取得集合的数据量

官网地址:https://docs.mongodb.com/manual/reference/operator/aggregation/count/#pipe._S_count

语法

// 直接查询
db.collection.count()

// 使用 find(),find函数中可以带入条件查询
db.collection.find().count();

// 直接在 count() 中带入条件查询(不建议使用)
db.collection.count({field : key})
// 插入数据
db.scores.insert({ "_id" : 1, "subject" : "History", "score" : 88 });
db.scores.insert({ "_id" : 2, "subject" : "History", "score" : 92 });
db.scores.insert({ "_id" : 3, "subject" : "History", "score" : 97 });
db.scores.insert({ "_id" : 4, "subject" : "History", "score" : 71 });
db.scores.insert({ "_id" : 5, "subject" : "History", "score" : 79 });
db.scores.insert({ "_id" : 6, "subject" : "History", "score" : 83 });

 示例

// 查询个数
> db.scores.count();
> db.scores.find().count();

示例:统计分数大于 80 的集合数据,并且将显示的字段命名分配给 passing_scorces

db.scores.aggregate([
    { $match: 
        { score: 
            { $gt: 80 }
        } 
    },
    { $count :"passing_scores" }
]);

"distinct"

官方链接:https://docs.mongodb.com/manual/reference/command/distinct/index.html

这个值的是消除重复数据,就类似于我们在 SQL 中的 distinct 操作。在 MongoDB 中存在这样子的操作,但是没有直接的函数提出,只能使用 runCommand() 实现。

首先准备一点数据:

db.getCollection('inventory').insertMany([
{ "_id": 1, "dept": "A", "item": { "sku": "111", "color": "red" }, "sizes": [ "S", "M" ] },
{ "_id": 2, "dept": "A", "item": { "sku": "111", "color": "blue" }, "sizes": [ "M", "L" ] },
{ "_id": 3, "dept": "B", "item": { "sku": "222", "color": "blue" }, "sizes": "S" },
{ "_id": 4, "dept": "A", "item": { "sku": "333", "color": "black" }, "sizes": [ "S" ] }
]);

示例:在 inventory 集合中,去除重复查询 dept 的值

db.runCommand ( { distinct: "inventory", key: "dept" } ); 

// 返回结果
{"values" : [ "A", "B" ], "ok" : 1.0};

示例:查询字节点的数据,在 inventory 中去除重复查询 item 节点下的 sku 的值

db.runCommand ( { distinct: "inventory", key: "item.sku" } ); 

// 返回结果 
{"values" : [ "111", "222", "333"],"ok" : 1.0}

"$sum"

$sum 进行求和操作。

官方地址:https://docs.mongodb.com/manual/reference/operator/aggregation/sum/#grp._S_sum

在后面介绍 "$group" 的时候还会 $sum 操作,这里介绍下另外一种操作。

准备数据如下:

{ "_id": 1, "quizzes": [ 10, 6, 7 ], "labs": [ 5, 8 ], "final": 80, "midterm": 75 }
{ "_id": 2, "quizzes": [ 9, 10 ], "labs": [ 8, 8 ], "final": 95, "midterm": 80 }
{ "_id": 3, "quizzes": [ 4, 5, 5 ], "labs": [ 6, 5 ], "final": 78, "midterm": 70 }

使用在 $project 层级里面的 $sum 操作

// 对明细数据求和(对"quizzes"、"labs"),以及对 "final" 与 "midterm" 做相加求和
db.students.aggregate([
   {
     $project: {
       quizTotal: { $sum: "$quizzes"},
       labTotal: { $sum: "$labs" },
       examTotal: { $sum: [ "$final", "$midterm" ] }
     }
   }
]);

// 返回结果
{ "_id" : 1, "quizTotal" : 23, "labTotal" : 13, "examTotal" : 155 }
{ "_id" : 2, "quizTotal" : 19, "labTotal" : 16, "examTotal" : 175 }
{ "_id" : 3, "quizTotal" : 14, "labTotal" : 11, "examTotal" : 148 }

"$unwind"

$unwind 可以将返回的数组数据,转换为字符串显示。数据使用的是"distinct" 中的数据

db.getCollection('inventory').aggregate([
    {"$unwind": "$sizes"}
]);

// 返回结果
{ "_id" : 1, "dept" : "A", "item" : { "sku" : "111", "color" : "red" }, "sizes": "S" }
{ "_id" : 1, "dept" : "A", "item" : { "sku" : "111", "color" : "red" }, "sizes": "M" }
{ "_id" : 2, "dept" : "A", "item" : { "sku" : "111", "color" : "blue" }, "sizes": "M" }
{ "_id" : 2, "dept" : "A", "item" : { "sku" : "111", "color" : "blue" }, "sizes": "L" }
{ "_id" : 3, "dept" : "B", "item" : { "sku" : "222", "color" : "blue" }, "sizes": "S" }
{ "_id" : 4, "dept" : "A", "item" : { "sku" : "333", "color" : "black" }, "sizes" : "S" }

"$out"

利用此操作可以将查询结果输出到指定的结果里。类似于我们在 SQL 做数据部分的复制备份。

使用的是 $sum 中的数据:

// 查询数据 
db.students.find();

示例:将 students 中的数据复制到 students_bak 中:

// $project 中是选择需要备份过去的字段
db.students.aggregate([
    { $project: {"quizzes": 1, "labs": 1, final: 1} },
    { $out: "students_bak" }
]);

// 查询刚刚备份的数据
db.students_bak.find();

从上面的操作可以看到,如果没有子啊 $project 中指明出 _id 字段,这个字段会自己复制过去。就类似于以下操作:

db.students.aggregate([
    { $project: {"_id": 1, "quizzes": 1, "labs": 1, final: 1} },
    { $out: "students_bak" }
]);

示例:测试备份出 _id 字段

// $project 中是选择需要备份过去的字段
db.students.aggregate([
    { $project: { "_id" : 0, "quizzes": 1, "labs": 1, "final": 1} },
    { $out: "students_info" }
]);

// 查询刚刚备份的数据
db.students_info.find();

如果我们指明不用备份 _id ,在复制的时候,就会自己创建出 _id 字段。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wayfreem

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值