Mongodb学习

聚合

基本语法

MongoDB 的 aggregate 操作使用 MongoDB 的聚合管道(Aggregation Pipeline)来处理数据。聚合管道是由多个阶段(stage)组成的序列,每个阶段执行一种特定的数据处理操作,将处理结果传递给下一个阶段,最终返回处理后的结果。

基本的 aggregate 操作语法如下:

db.collection.aggregate([
   { <stage1> },
   { <stage2> },
   ...
   { <stageN> }
])

db.sales.aggregate([
    {
        $group : {
            _id : "$item",
            totalPrice: { $sum : "$price"},
            avgQuantity: { $avg: "$quantity" }
        }
    }
]);

常用聚合阶段(Stages)

MongoDB 的聚合管道中常用的阶段有:

  • $match 阶段:用于筛选文档,只传递满足指定条件的文档到下一个阶段。

    { $match: { <条件> } }

  • $project 阶段:格式化输出,用于重新定义文档的结构,包括字段重命名、增加或删除字段等操作。

    { $project: { <字段1>: 1, <字段2>: 1, ... } }

  • $group 阶段:根据指定的键对文档进行分组,并计算每个组的聚合结果。

    { $group: { _id: <分组键>, <聚合操作> } }

  • $sort 阶段:对文档进行排序。

    { $sort: { <排序字段>: 1 } } // 1 表示升序,-1 表示降序

  • $limit 阶段:限制返回的文档数量。

    { $limit: <数量> }

  • $skip 阶段:跳过指定数量的文档,用于分页。

    { $skip: <数量> }

不常用

  • $unwind 阶段:将包含数组的字段拆分成多个文档,每个数组元素对应一个文档。

    { $unwind: "$arrayField" }

  • $lookup 阶段:在同一个数据库中,从其他文档中寻找匹配的文档。

实验

1)查看系统中已有的数据库;

show databases
show dbs

2)创建自定义数据库,名称为:NoSQL;

use NoSQL

3)查看当前数据库列表,是否能够查到刚刚创建的数据库?为什么查不到?

查不到

4)插入数据,使得这个数据库可以被查到。

db.collection.insertOne({key: value})
db.users.insertOne({name: "John", age: 25})

5)统计该数据库的信息;

db.stats()

6)删除数据库;

use NoSQL
db.dropDatabase()

集合操作:

1)隐式创建集合

use NoSQL
db.collectionName.insertOne({key: value})

2)显式创建集合

use NoSQL
db.createCollection("test")

3)更改集合的名字

MongoDB 不支持直接更改集合的名称,你需要使用以下步骤来完成重命名操作:

  • 将集合的数据复制到一个新的集合中。
  • 删除原始集合。
db.collection1.renameCollection("xxx")

4)查询当前数据库下所有的集合

show collections

5)删除创建的集合

use NoSQL
db.users.drop()

1、插入文档

img

use school;

db.students.insertMany([
    {_id: 1308091001, class: '13级计科2班', name: '项青宇', sex: '男', chinese: 100, math: 100, english: 100, computer: 100},
    {_id: 1308091002, class: '13级计科2班', name: '许琨琪', sex: '女', chinese: 99, math: 98, english: 97, computer: 99},
    {_id: 1308091003, class: '13级计科2班', name: '张杰', sex: '女', chinese: 68, math: 87, english: 88, computer: 77},
    {_id: 1308091004, class: '13级计科2班', name: '杨朴', sex: '女', chinese: 87, math: 77, english: 68, computer: 87},
    {_id: 1308091005, class: '13级计科2班', name: '刘翠芳', sex: '女', chinese: 74, math: 69, english: 79, computer: 84},
    {_id: 1308091006, class: '13级计科2班', name: '王伟', sex: '男', chinese: 82, math: 84, english: 54, computer: 92},
    {_id: 1308091007, class: '13级计科2班', name: '林梦婷', sex: '女', chinese: 81, math: 74, english: 87, computer: 94},
    {_id: 1308091008, class: '13级计科2班', name: '黄创', sex: '男', chinese: 64, math: 65, english: 64, computer: 85},
    {_id: 1308091009, class: '13级计科3班', name: '管浩森', sex: '男', chinese: 91, math: 78, english: 90, computer: 98},
    {_id: 1308091010, class: '13级计科3班', name: '苏小妍', sex: '女', chinese: 87, math: 67, english: 99, computer: 95}
]);

2、更新操作

将项青宇的语文成绩改为98、数学成绩改为99;

db.students.updateOne(
    {name: '项青宇'},
    {$set: {chinese: 98, math: 99}}
);

3、删除操作

将语文成绩为87的文档删除

db.students.deleteMany({chinese: 87});

4、查询操作:

查询语文成绩大于80的文档;
db.students.find({chinese: {$gt: 80}}).pretty();

查询数学成绩小于60的文档;
db.students.find({math: {$lt: 60}}).pretty();

查询英语成绩大于等于75的文档;
db.students.find({english: {$gte: 75}}).pretty();

查询计算机成绩小于等于89的文档;
db.students.find({computer: {$lte: 89}}).pretty();

查询班级为“13级计科2班”且语文成绩大于60的文档;
db.students.find({class: '13级计科2班', chinese: {$gt: 60}}).pretty();

查询班级为“13级计科2班”语文成绩或数学成绩大于80的文档;
db.students.find({class: '13级计科2班', $or: [{chinese: {$gt: 80}}, {math: {$gt: 80}}]}).pretty();

查询班级为“13级计科2班”语文成绩或数学成绩大于80的文档,并跳过前两条数据;
db.students.find({class: '13级计科2班', $or: [{chinese: {$gt: 80}}, {math: {$gt: 80}}]}).skip(2).pretty();

查询班级为“13级计科2班”语文成绩或数学成绩大于80的文档,并仅输出3条数据;
db.students.find({class: '13级计科2班', $or: [{chinese: {$gt: 80}}, {math: {$gt: 80}}]}).limit(3).pretty();

查询班级为“13级计科2班”语文成绩或数学成绩大于80的文档,跳过1条数据,并仅输出2条数据;
db.students.find({class: '13级计科2班', $or: [{chinese: {$gt: 80}}, {math: {$gt: 80}}]}).skip(1).limit(2).pretty();

查询班级为“13级计科2班”语文成绩或数学成绩大于80的文档,并按照语文成绩倒序进行输出。
db.students.find({class: '13级计科2班', $or: [{chinese: {$gt: 80}}, {math: {$gt: 80}}]}).sort({chinese: -1}).pretty();

查询班级为“13级计科2班”语文成绩小于60的文档,并仅输出姓名和语文成绩。
db.students.find({class: '13级计科2班', chinese: {$lt: 60}}, {name: 1, chinese: 1, _id: 0}).pretty();

索引:

1、创建单键索引

db.grade.createIndex({语文:-1})

2、删除单键索引

db.grade.dropIndex({语文:-1})

3、利用索引进行查询,并查看查询过程

db.grade.find({“语文”: {$lt:60}}).explain()

4、复合索引

db.grade.createIndex({“姓名”:1,“语文”:-1})

利用索引进行查询,并查看查询过程

db.grade.find({“姓名”:‘项青宇’}).explain()

管道:

1、求和:sum

每个班级的人数

db.grade.aggregate([
    { $group: { _id: "$班级", 学生人数: { $sum: 1 } } }
]);

2、各班语文的成绩的最大值/最小值

db.grade.aggregate([
    { $group: { _id: "$班级", 语文最高分: { $max: "$语文" } } }
]);
db.grade.aggregate([
    { $group: { _id: "$班级", 语文最低分: { $min: "$语文" } } }
]);

3、各班语文的成绩的平均值

db.grade.aggregate([
    { $group: { _id: "$班级", 语文平均分: { $avg: "$语文" } } }
]);

4、$project:显示结果的字段进行调整

db.grade.aggregate([
    { $group: { _id: null, 学生人数: { $sum: 1 } } },
    { $project: { "学生人数": 1, _id: 0 } }
]);

5、$match:过滤输出条件

输出语文成绩大于80且班级为计科三班的文档,仅输出姓名、语文成绩字段

db.grade.aggregate([
    { $match: { 语文: { $gt: 80 }, 班级: '计科三班' } },
    { $project: { 姓名: 1, 语文: 1, _id: 0 } }
]);

6、$sort:结果排序

输出语文成绩大于80且班级为计科三班的文档,并按照语文成绩降序输出,仅输出姓名、语文成绩字段

db.grade.aggregate([
    { $match: { 语文: { $gt: 80 }, 班级: '计科三班' } },
    { $project: { 姓名: 1, 语文: 1, _id: 0 } },
    { $sort: { 语文: -1 } }
]);

7、$limit限制显示结果

输出语文成绩大于80的文档前,并按照语文成绩降序输出,仅输出姓名、语文成绩字段,仅输出符合条件的前两个数据

db.grade.aggregate([
    { $match: { 语文: { $gt: 80 } } },
    { $project: { 姓名: 1, 语文: 1, _id: 0 } },
    { $sort: { 语文: -1 } },
    { $limit: 2 }
]);

8、$skip略过返回结果的前几项

输出语文成绩大于80的文档前,并按照语文成绩降序输出,仅输出姓名、语文成绩字段,仅输出符合条件的前两个数据,并跳过第一条数据

db.grade.aggregate([
    { $match: { 语文: { $gt: 80 } } },
    { $project: { 姓名: 1, 语文: 1, _id: 0 } },
    { $sort: { 语文: -1 } },
    { $skip: 1 },
    { $limit: 2 }
]);

9、输出语文成绩大于70小于等于90的人数

db.grade.aggregate([
    { $match: { 语文: { $gt: 70, $lte: 90 } } },
    { $group: { _id: null, 人数: { $sum: 1 } } },
    { $project: { 人数: 1, _id: 0 } }
]);
0%