MongoDB学习笔记

MongoDB介绍

MongoDB是一个基于分布式文件存储的数据库,由C++编写,旨在为WEB应用提供可扩展的高性能数据库存储解决方案。
特点:高性能,易部署,易使用,存储数据方便。
MongoDB是一个介于关系数据库和非关系数据库之间的产品。是非关系数据库中功能最丰富最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。。MongoDB最大的特点就是它支持的查询语言非常强大,类似于面向对象的查询语言,几乎可以实现类似关系数据库的单表查询的绝大部分功能。

关系型数据库和非关系型数据库是两种不同的数据存储方式。关系型数据库通过二维表维持数据关系,需要预先定义数据结构,支持事务处理,安全性高,但查询速度慢,只能存储基础类型。非关系型数据库通过键值对维持数据关系,数据结构灵活,查询速度快,可以存储多种格式的数据,但不支持事务处理,安全性低。

MongoDB中的基础概念

MongoDB中的基础概念:文档,集合,数据库
下图是mysql和MongoDB的区别
在这里插入图片描述

一个MongoDB可以创建多个数据库,默认数据库为db,该数据库存储在data目录中。单个实例可以容纳多个独立的数据库,每个数据库都有自己的集合和权限,不同的数据库防在不同的文件中。数据库命名采用标识符,一般是utf-8字符串,不能为空,不能用local/admin/config这三个

文档

文档是一个键值对,MongoDB的文档不需要设置相同的字段,相同的字段不需要相同的数据类型,这与关系型数据库有很大区别,也是MongoDB非常突出的特点。
一个示例

{"title":"我是标题","content":"没有内容"}

集合

集合就是MongoDB文档组,类似于RDBMS,关系数据库管理系统中的表格
集合存在于数据库中,集合没有固定的结构,这意味着你在集合中可以插入不同格式和类型的数据,但是通常情况下我们插入集合的数据都会有一定的关联性。集合的命名不能使空字符串。也不能出现-,0等,不能以system,$开头
当第一个文档插入时,集合就会被创建。

数据库

MongoDB中常用的几种数据类型

  1. String − 这是最常用的用于存储数据的数据类型。在MongoDB中,字符串必须是UTF-8格式的。
  2. Integer − 这种类型用于存储数字值。整数可以是32位或64位,取决于服务器。
  3. Boolean − 这种类型用于存储布尔值(true/false)。
  4. Double − 这种类型用于存储浮点数值。
  5. Min/ Max键 − 这种类型用于将值与最低和最高的BSON元素进行比较。
  6. Arrays − 这种类型用于将数组、列表或多个值存储到一个键中。
  7. Timestamp − 时间戳。这对于记录文档的修改或添加时间非常有用。
  8. Object − 这种数据类型用于嵌入式文档。
  9. Null − 这种类型用于存储空值。
  10. Symbol − 这种数据类型与字符串的使用方式相同;然而,它通常用于使用特定符号类型的语言。12.
  11. Date − 这种数据类型用于以UNIX时间格式存储当前日期或时间。您可以通过创建Date对象并将日期、月份、年份传递给它来指定自己的日期时间。
  12. Object ID − 这种数据类型用于存储文档的ID。
  13. 二进制数据 − 这种数据类型用于存储二进制数据。
  14. Code − 这种数据类型用于将JavaScript代码存储到文档中。
  15. 正则表达式 − 这种数据类型用于存储正则表达式。

ObjectId

ObjectId类似唯一主键,可以很快的生成排序。
MongoDB中存储的文件必须有一个_id键,这个键的值可以是任何类型的,默认是个ObjectId对象。

字符串

BSON字符串都是UTF-8编码

MongoDB安装

可视化工具Studio 3T

查看相关文档安装MongoDB,使用可视化工具Studio 3T操作数据库。
都可以到官网下载相关安装文件,安装完之后使用Studio 3T。
利用可视化界面来操作数据库的增删改查,安装的目的是为了我们使用代码操作的时候,更方便的查看操作的结果。使用可视化工具要保证数据库是开启状态。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

之后save即可
在这里插入图片描述
在这里插入图片描述

左侧点击
在这里插入图片描述

选择shell,在命令行输入命令。

MongoDB命令

创建数据库,不存在就创建,存在就切换到指定数据库。(blog为数据库名称)

use blog

在这里插入图片描述

查看所有数据库

show  dbs

在这里插入图片描述

在数据库里创建数据表users

db.createCollection(users)

在这里插入图片描述

左侧如果没有显示,刷新所有即可。
在这里插入图片描述

document 文档操作

db.集合名.方法名

可以在集合中插入文档信息

db.users.insert({"username":"zhang","password":"123456"})
db.users.insertOne({"username":"zhangsan","password":"123456"})
db.users.insertMany([{"username":"zhangsan","password":"123456"}])

插入操作如果执行多次,就会插入多个文档

查询文档

db.users.find({"username":"zhangsan"})
db.users.findOne({"username":"zhangsan"})

在这里插入图片描述
在这里插入图片描述

更新文档

db.users.update({username:'zhangsan'},{$set:{username:'lisa'}})

在这里插入图片描述
在这里插入图片描述

多次执行可以将多个相同的文档数据逐个更新

db.users.update({username:'lisa'},{$inc:{age:18}})

上面的命令可以为lisa添加age属性
在这里插入图片描述

删除文档

删除年龄是18的

db.users.deleteOne({age:18});

在这里插入图片描述
在这里插入图片描述

删除user中所有数据

db.user.deleteMany({})

在这里插入图片描述

条件查询

范围查询

查询age=18的记录

db.users.find({"age":18})

在这里插入图片描述

查询age>18的记录

db.users.find({"age":{$gt:18}})

在这里插入图片描述

查询age<18的记录

db.users.find({"age":{$lt:18}})

查询13<=age<=100的记录

db.users.find({age:{$gte:13,$lte:100}});

在这里插入图片描述

筛选数据

查询指定列name,age数据

db.users.find({},{username:1,age:0})//1为显示,0为不显示。

在这里插入图片描述

如果只查看前5条数据。

db.users.find({},{username:1},{age:0}).limit(5)

在这里插入图片描述

查看10条以后的数据。

db.users.find({},{username:1},{age:0}).skip(1)

在这里插入图片描述

限制数据量

db.users.find({"username":"zhan"},{age:0}).limit(1).skip(1)

在这里插入图片描述

查询指定列age数据,age>15

db.users.find({age:{$gt:15}},{username:0},{age:1})

在这里插入图片描述

排序

按照年龄排序
升序

db.users.find().sort({age:1})

在这里插入图片描述

降序

db.users.find().sort({age:-1})

在这里插入图片描述

属性值为空的升序在最上面,降序在最下面。

Mongoose

一个第三方库,在express中利用mongoose库操作MongoDB比较方便。
mongoose为模型提供一种直接的基于scheme结构去定义数据结构。它内置数据验证,查询构建,业务逻辑钩子等,开箱即用。
简单来说,可以使用mongoose定义数据的表结构,表结构在mongoose中叫scheme,然后直接使用表结构创建一个数据模型。我们使用数据模型就可以操作数据库中的对应的表。这里的表不需要自己创建,直接使用数据模块,他会自动创建表。

mongoose的使用方式

安装mongoose

npm 初始化项目
安装 mongoose
npm i mongoose

引入模块,连接数据库

创建models文件夹,存放数据库的模型相关操作,新建文件index.js

//引入模块
let mongoose = require('mongoose');
//连接数据库
mongoose.connect('mongodb://127.0.0.1/blog').then(res => {
    console.log('success');
}).catch(err)=> {
    console.log("fail");
};

如果使用localhost失败可以使用127.0.0.1

mongoose中的对象

schema模式对象(用于约束文档的结构-类似表头)
model模型对象(MongoDB中的集合-表)
document文档对象(即MongoDB中的文档-表中一行数据)

Schema

mongoose中的一切起始于Schema。每个Schema都会映射到一个MongoDB 集合上,并定义这个集合里的文档(一行数据)的构成。

//获取创建集合的模块
let Schema = mongoose.Schema;
//新建文章表结构
let ArticleSchema = new Schema(
    {
        title: String,//文章标题
        content: String,//文章内容
        tag: String,//文章分类
        author: String,//文章作者
        views: {
            type: Number,
            default: 0,
        },//文章的浏览量
    },
    {
        timestamps: true,//启用时间戳时,mongoose会将createAt和updatedAt属性添加到模型中,表中添加一行数据的时候会产生时间戳,记录,数据的创建时间和修改时间
    }
);

Model

Models是从Schema编译来的构造函数,它们的实例就代表可以从数据库保存和读取的documents。从数据库创建和读取document的所有操作都是通过model进行的。
通过它可以对表的内容进行增删改查

// 根据表结构创建数据模型,并把表结构映射数据中一个表Articles
// article通过这个对象我们就可以对数据库中的数据进行增删改查
let Article = mongoose.model('Article', ArticleSchema);

第一个参数是跟model对应的集合名字,将表结构ArticleSchema绑定到当前数据库上,并且得到操作表中内容的构造函数。用这些构造函数可以创建表中的数据,进行CRUD增删改查。
注意,当向表中插入数据的时候表才会生成,表的名字自动使用复数的形式,比如刚刚构造函数Article,在使用的时候会自动在数据库中创建一个Articles表。

创建文档数据,插入表中

// 创建数据,保存到数据库
Article.create({
    title: "给学妹的信",
    content: "每逢佳节倍思亲",
    author: "zhagsan",
    tag: "信件",
}).then((res) => {
    console.log(res);
    console.log("爆粗成功")
});

下面也可以

let atr=new Article({
    title: "给x的信",
    content: "每逢佳节倍思亲",
    author: "zhagsan",
    tag: "信件",
});
//保存到数据库
atr.save().then((res)=>{
    console.log(res);
    console.log("保存成功");
});

终端进入models安装mongoose执行nodemon index.js
在这里插入图片描述

也可以在创建数据的时候在对象里面写一个数组包含着多个对象。
在blog数据库中可以看到articles集合及其数据。

删除数据

第一个参数是一个对象,对象内是条件

  1. 删除指定id的文章
Article.deleteOne({ _id: '66a05e2bb682caaad9a91f6b' }).then(res => {
    console.log('删除成功');
    console.log(res);
}).catch(err => {
    console.log('删除失败');
})

在这里插入图片描述

  1. 删除包含指定内容的数据
Article.deleteMany({ content:/每逢佳节/ }).then(res => {
    console.log('删除成功');
    console.log(res);
})

在这里插入图片描述

修改数据

第一个参数对象是一个条件
第二个参数对象是一个要修改的内容

//指定id文章修改内容
Article.updateOne({ _id: '66a05df8a4bbca4482cdd133' }, { title: 'aaa' }).then(res => {
    console.log('修改成功');
})

上述代码实现修改文章标题为aaa
根据id修改views字段,自加1,并且修改的时候不易绕过updateAt更新

Article.updateOne(
    {
        _id: '66a077c6e960d145a3912b2c'
    },
    {
        $inc: { views: 1 }//views字段自加1
    },
    {
        timestamps: false//修改不让updateAt自增
    }
).then((res) => {
    console.log("修改成功");
    console.log(res);
})
    .catch((err) => {
        console.log("修改失败");
    });

在这里插入图片描述

在这里插入图片描述

查询数据

查询多条数据
能查询多条,也可以传入条件

Article.find({ views: { $gte: 0, $lte: 1000 },  title: /x/ })//搜索包含x的数据,使用正则匹配
  .sort({ views: -1 })//根据views排序 1升序  -1降序
   .skip(1)//跳过前0条
   .limit(10)//获取10条事件
   .select({author:0})//1 查询结果中出现author字段,0是不出现这个字段
   .exec()//执行查询
   .then((r) => {
       console.log(r)
   });

  1. 根据id查询一条数据
Article.findOne({ _id: "66a077c6e960d145a3912b2c" }).then((err) => {
    console.log(err)
})
Article.findById("66a077c6e960d145a3912b2c").then((err) => {
    console.log(err);
});
Article.findByIdAndUpdate('66a077c6e960d145a3912b2c', { $inc: { views: 1 } }, { timestamps: false }).then(r => {
    console.log(r);
});

图为最后一个代码运行结果,代码第一次执行是原来的views,再次执行,views加1
在这里插入图片描述

  1. 查询浏览量在1-1000的数据,标题包含x的数据
// 浏览量1-1000,标题包含x的数据
Article.find({ views: { $gte: 0, $lte: 1000 }, title: /x/ })
    .exec()
    .then((r) => {
        console.log(r)
    });

排序

根据文章views进行降序排序

Article.find({ views: { $gte: 0, $lte: 1000 }, title: /x/ })
    .sort({views: -1 })
    .exec()
    .then((r) => {
        console.log(r)
    });

局部截图
在这里插入图片描述

聚合函数

聚合函数是数据库操作中不可或缺的一部分。
下图是一些常用的聚合函数表达式
在这里插入图片描述
参与示例的集合数据如下
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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

有点类似 SQL 语句中的 count(*)
语法:>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

计算每个学生的学科总分数,使用aggregate()计算

db.scores.aggregate([
  { $group: {
      _id: "$studentName",  // 根据学生姓名分组
      totalScore: { $sum: "$score" }  // 计算学科总分数
  }}
])

查询学生的个人信息以及班级信息

需要多表联查,使用$lookup联合student集合以及class集合

//管道查询,联合查询
db.getCollection("student").aggregate([{
    $lookup: {
        from: "class",
        localField: "id",
        foreignField: "stuid",
        as: "student_class"
    }
}])

查询小九的学生信息

//管道查询,联合查询,$match过滤条件查询
db.getCollection("student").aggregate([{
    $lookup: {
        from: "class",
        localField: "id",
        foreignField: "stuid",
        as: "student_class"
    }
}, {
    $match: {
        name: "小九"
    }
}])

//两表关联,每个表都有条件
db.getCollection('student').aggregate([
    {
        $match: {
            name: "小明"
        }
    },
    {
        $lookup: {
            from: "class",
            localField: "id",
            foreignField: "stuid",
            as: "student_class"
        }
    },
    {
        $match: {
            "student_class.master": "老李"
        }
    }
])

查看学生课程信息

//遍历数组数据
db.getCollection('student').aggregate([
   {
      $unwind: "$course"
   }
])

//管道查询,联合查询,$unwind数组便利,$match过滤条件查询
db.getCollection('student').aggregate([
    {
        $unwind: "$course"
    },
    {
        $lookup: {
            from: "class",
            localField: "id",
            foreignField: "stuid",
            as: "student_class"
        }
    },
    {
        $match: {
            name: "小明"
        }
    }
])

显示指定同学的姓名和年龄

$project可以用来提取想要的字段,1表示要该字段,0表示不要该字段,也可以对返回的字段进行重命名:

//管道查询,联合查询,$unwind数组便利,$match过滤条件查询,$project设置需要返回的字段属性
db.getCollection('student').aggregate([
    {
        $unwind: "$course"
    },
    {
        $lookup: {
            from: "class",
            localField: "id",
            foreignField: "stuid",
            as: "student_class"
        }
    },
    {
        $match: {
            name: "小明"
        }
    },
    {
        $project: {
            name: 1,
            age: 1
        }
    }
])

返回数据库的student集合中的前两条数据

//返回前两条数据
db.getCollection("student").aggregate([{
    $lookup: {
        from: "class",
        localField: "id",
        foreignField: "stuid",
        as: "student_class"
    }
}, {
    $limit: 2
}])

跳过student的第一条数据并返回两个文档

//跳过第一个文档并返回两个文档
db.getCollection("student").aggregate([{
    $lookup: {
        from: "class",
        localField: "id",
        foreignField: "stuid",
        as: "student_class"
    }
}, {
    $skip: 1
}, {
    $limit: 2
}])

注意: s k i p 语句应该在 skip语句应该在 skip语句应该在limit之前。

按照班级分组查询

//分组查询
db.getCollection("class").aggregate([{
    $group: {
        _id: "$master",
        count: {
            $sum: 1
        }
    }
}])

将学生集合按照id号降序排序

将查询结果按照某个字段进行排序,相当于mysql的order by语句,1表示升序,-1表示降序,默认为升序显示。


//排序
db.getCollection("student").aggregate([{
    $sort: {
        id: -1
    }
}])

管道的概念

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。

MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。

这里我们介绍一下聚合框架中常用的几个操作:

$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
m a t c h :用于过滤数据,只输出符合条件的文档。 match:用于过滤数据,只输出符合条件的文档。 match:用于过滤数据,只输出符合条件的文档。match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$geoNear:输出接近某一地理位置的有序文档。

  • 24
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

隐藏用户y

虽然不是很有才华,但是渴望打赏

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

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

打赏作者

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

抵扣说明:

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

余额充值