目录
-
数据库概念
-
数据库交互
- MongoDB
- mongoose
一、数据库概念
1.1 数据库简介
-
概念:数据库本身就是数据的
仓库
,即保存数据的地方。电脑中的数据也是通过软件来保存,不同的公司开发出了不同的数据库软件。大体上各个数据库可以分为两类:关系数据库和非关系型数据库 -
关系型数据库
-
指 数据库里的数据和数据之间都有一定的关联,那么称这样的数据库为关系数据库。
-
常见关系型数据库
-
MySQL
- 免费,适合中小型数据库。比如千万级以下的数据保存
-
SqlServer:微软开发,收费的,绑定于Windows平台。适合于中大型数据库。数据基本是超过千万级以上的。
-
oracle:sun公司开发的,收费。拥有丰富的功能,以及很好的安全性。适合中大型数据库。但环境比较复杂。
-
-
关系型数据库优缺点
- 结构统一,方便维护
- 查询比较慢(一般关系型数据库是依次遍历的)
-
应用
- 一般会作为数据库保存项目的所有数据
-
-
非关系型数据库
-
概念:no sql,指的阉割版本的关系数据库。可以采用不同的格式来保存数据,有的使用对象来保存数据,有的使用字符串保存数据。
-
特点
- 因为设计出来就是为了更快的查询数据,所以基本只保留了管理数据的基本架构,以及对保存的数据格式各种各样。
-
常见
- MongoDB
- Redis
- H2
- indexDB
- ….
-
优缺点
- 查询极快,根据编号来查。
- 插入(添加)比较麻烦
-
应用
- 一般会作为小型数据库进行保存数据(MongoDB)
- 作为缓存数据库来使用(Redis)
-
二、 MongoDB
2.1 mongodb 简介
-
概念:MongoDB是一款非关系型数据库软件。
-
引入
- 下载安装包并安装后进行使用:www.mongodb.com/try/downloa…
- 打开安装界面,一路next,只不过在最后一步有个勾选的
install mongodb compass
去掉勾选。再进行安装。
-
测试是否成功安装
-
安装结束后,开始栏搜索计算机管理,点击进去之后再服务和应用程序板块,双击后选择服务,查看MongoDB服务是否已经启动,以下是正常成功启动状态。
-
2.2 mongodb 相关概念
2.2.1 数据概念
- mongodb可以有多个数据库。每个数据库由多个集合构成,每个集合(conlection)可以用于保存某一类的数据。比如订单集合可以保存所有的 订单数据。用户集合可以保存所有的用户数据。 每个集合都可以保存多个具体的数据(文档-document),每个文档本质上是一个对象。
- 集合:一类数据的集合。每个集合可以保存多个数据。一般一个集合就保存同一类的数据。订单集合就保存订单数据,用户集合就保存用户数据,每个集合保存的每个数据又称为一个文档。
- 文档:集合里保存的数据单位。本质是一个对象。
- _id:是每次向数据库添加数据会自动生成的随机编码。这个在整个MongoDB中是唯一的,可以理解为该条数据(文档)的
身份证
号码。理由该身份证可以找到该数据。
2.3 使用MongoDB
-
使用MongoDB一般有两种方式
- 使用cmd(命令提示符)即终端操作数据库
- 安装第三方开发的可视化工具进行操作。比如navicat(收费)
二、Mongoose 数据库交互
- 前提:Nodejs提供了一个npm包:
mongoose
用于完成程序与MongoDB数据库的交互 - 目的:学习使用mongoose链接数据库并实现和某个集合的数据交互
2.1 下载mongoose
-
利用npm下载mongoose:项目根目录下下载mongoose
npm i mongoose
2.2 链接MongoDB数据库
-
需要在项目app.js中引入mongoose并使用其api完成数据库的链接
const mongoose = require('mongoose'); //1.指定连接数据库的路径 127.0.0.1 const url = 'mongodb://localhost:27017/数据库名称'; // 2. 去掉严格查询警告,从mongoose7之后会变为默认false,在6.x作为提示 mongoose.set('strictQuery',false); //3.mongoose提供的api进行连接 mongoose.connect(url); //4. 监听已连接事件,输出已连接 mongoose.connection.on('connected',function(){ //已连接成功后会执行的函数 console.log('MongoDB已连接:'+url); });
- 建议代码写在app.js头部区域,即引入routes路由文件之前。
- 如果连接失败,可以尝试将url中的
localhost
切换成127.0.0.1
再次尝试
2.3 引入指定集合数据到程序
-
前提
- 因为MongoDB数据库的一些数据类型是Nodejs不支持 的(比如ObjectId),为了保证数据库的数据能够正确的在程序中显示出来,我们需要利用Schema对象完成文档和Nodejs对象的数据类型的转换
-
大概流程
- 需要先基于要使用的集合先创建一个集合模型Schema对象,之后再利用该对象和要使用的集合进行关联,之后就可以使用mongoose提供的api进行数据的增删查改等操作
-
详细流程
-
1.在处理该数据的路由js文件中引入mongoose
const mongoose = require('mongoose');
-
2.创建Schema模型对象,完成数据库文档和Nodejs对象属性的数据类型的转换
const userSchema = new mongoose.Schema({ //_id是自动引入并转换 username:String, password:String },{ //取消_v字段生成 versionKey:false })
-
3.基于第二步新建的Schema对象完成和数据库指定集合的关联,关联之后会得到集合对象
let userModel = mongoose.model("userModel",userSchema,'users')
- 第一个参数:一个字符串,表示该集合在mongoose注册的集合模型名称,唯一的,不能重复注册。主要方便在多集合关联查询时使用,推荐名称为
集合名Model
- 第二个参数:要关联的模型schema对象
- 第三个参数:要和模型schema对象关联的集合名称(数据库里的集合)
- 第一个参数:一个字符串,表示该集合在mongoose注册的集合模型名称,唯一的,不能重复注册。主要方便在多集合关联查询时使用,推荐名称为
-
4.基于第三步生成的集合对象调用相关api完成数据的增删查改操作.比如查询所有的数据
router.get('/findAll',async function(req,res){ let result =await userModel.find(); console.log(result); })
-
2.4 集合对象的常用api
-
常用api
- find:查询
- create:新建
- updateMany:修改
- deleteMany:删除
- skip:跳过
- limit:限制返回的数据个数
- countDocuments:返回集合的数据个数
2.4.1 查询:find
-
目的:完成各种条件的数据查询
-
语法
-
基本语法
集合对象名.find(条件对象)
-
查询所有
集合对象名.find()
-
带条件的查询
1. 单条件查询:查询username为张三的所有数据 集合对象名.find({username:'张三'}) 2. 多条件查询:查询username为张三并且password为zs123的所有数据 集合对象名.find({username:'张三',password:'zs123'}) 3. 模糊查询:查询username包含三的所有数据 集合对象名.find({ username:{$regex:/三/,$options:"$i"}, }) 集合对象名.find({ username:{$regex:new RegExp("三"),$options:"$i"}, }) 4. 任意其中一个条件满足即可。查询username为张三或李四的所有数据 集合对象名.find({ $or:[ {username:"张三"}, {username:'李四'} ] })
-
2.4.2 添加:create
-
语法
1. 添加一个数据 let result = await 集合对象名.create(数据对象) //result拿到的就是新建的对象本身,也包含了_id 2. 批量添加 let result = await 集合对象名.create(对象数组)
- 在添加之后可能数据库集合会多了一个
_v
字段,表示版本号,如果不需要,则修改集合的schema对象,详情见2.3
- 在添加之后可能数据库集合会多了一个
2.4.3 删除:deleteMany
-
语法
let result = await 集合对象名.deleteMany(条件对象);console.log(result.deletedCount)
- result对象返回的是删除的信息,其中有一个
deletedCount
表示被删除数据的数量 - deleteMany对象所需的条件对象用法参考find()
- result对象返回的是删除的信息,其中有一个
2.4.4 修改:updateMany
-
语法
let result = 集合对象名.updateMany(条件对象,更新对象)
- 第一个参数:用于筛选满足条件的数据,也就是待修改的数据
- 第二个参数:一个对象,用于表示需要修改的数据
- result返回的是一个对象,里面有个属性
modifiedCount
表示修改的数据的数量,以此作为是否修改成功的判断条件
2.4.5 跳过:skip
-
作用:跳过已查到数据的前面指定数量的数据
-
语法
let result = await 集合对象名.find(条件对象).skip(数字)
- skip需要一个大于等于0 的数字,如果为负数会报错
2.4.6 限制个数:limit
-
作用:限制查询数据的数量,可以和skip搭配使用。可以实现查询集合处于中间的部分数据
-
语法
let result = await 集合对象名.find(条件对象).limit(数字)
- limit里的是一个大于等于0的数字,表示实际返回给前端数据的数量,相当于进行截取操作
2.4.7 文档数量:countDocuments
-
作用:返回该集合里数据的总数量
-
语法
let result = await 集合对象名.countDocuments()
2.5 多集合关联查询
-
前提:当一个集合中包含了其他集合的数据时,针对该集合的查询就称为多集合关联查询。默认情况下只能得到关联集合的
_id
.实际需要通过新api将关联_id转为具体的数据 -
概念:需要通过修改集合Schema对象以及采用新api
populate
来实现完整的查询。 -
大概流程
- 修改待查询集合的Schema模型对象,将关联集合部分进行修改,修改后再查询数据时搭配populate来实现关联查询
-
详细流程
-
1.需要修改待查询集合的Schema模型对象代码,以movies集合为例。
const moviesSchema = new mongoose.Schema({ //_id是自动引入并转换 //Array Number Boolean String "actors":Array, "director":{ type:mongoose.SchemaTypes.ObjectId, ref:"导演集合名称" }, "movieType": "movieType":[{ type:mongoose.SchemaTypes.ObjectId, ref:'movieTypesModel' }], //... 其他属性 },{ //取消_v字段生成 versionKey:false })
- ref属性写的是关联集合的模型名称,不是属性名,模型名称可以在关联集合的
mongoose.model
的第一个参数中获取
- ref属性写的是关联集合的模型名称,不是属性名,模型名称可以在关联集合的
-
2.在查询movies集合的时候,要搭配使用populate实现关联查询
let result = await movieModel.find().populate("director").populate('movieType')
- populate所需的参数是待查询集合中关联其他集合的属性名。当前因为跟导演集合管理的属性名是director,所以就写director
-
3.查看查询效果
-