【Node.js】(四)MongoDB、接口、会话控制

十一. mongoDB

1. 简介

MongoDB 是一个基于分布式文件存储的数据库,官方地址 https://www.mongodb.com/
数据库(DataBase)是按照数据结构来组织、存储和管理数据的 应用程序
数据库的主要作用就是 管理数据 ,对数据进行 增(c)、删(d)、改(u)、查(r)

  1. 数据库管理数据的特点

相比于纯文件管理数据,数据库管理数据有如下特点:

  • 速度更快
  • 扩展性更强
  • 安全性更强
  1. 为什么选择Mongodb

操作语法与JavaScript类似,容易上手,学习成本低

2. 核心概念

Mongodb 中有三个重要概念需要掌握

  • 数据库(database) 数据库是一个数据仓库,数据库服务下可以创建很多数据库,数据库中可以存放很多集合
  • 集合(collection) 集合类似于 JS 中的数组,在集合中可以存放很多文档
  • 文档(document) 文档是数据库中的最小单位,类似于 JS 中的对象

【Node.js】(四)MongoDB、接口、会话控制_第1张图片
JSON 文件示例:

{
  "accounts": [
    {
      "id": "3-YLju5f3",
      "title": "买电脑",
      "time": "2023-02-08",
      "type": "-1",
      "account": "5500",
      "remarks": "为了上网课"
    },
    {
      "id": "3-YLju5f4",
      "title": "请女朋友吃饭",
      "time": "2023-02-08",
      "type": "-1",
      "account": "214",
      "remarks": "情人节聚餐"
    },
    {
      "id": "mRQiD4s3K",
      "title": "发工资",
      "time": "2023-02-19",
      "type": "1",
      "account": "4396",
      "remarks": "终于发工资啦!~~"
    }
  ],
  "users": [
    {
      "id": 1,
      "name": "zhangsan",
      "age": 18
    },
    {
      "id": 2,
      "name": "lisi",
      "age": 20
    },
    {
      "id": 3,
      "name": "wangwu",
      "age": 22
    }
  ]
}
  • 一个 JSON 文件 好比是一个 数据库 ,一个 Mongodb 服务下可以有 N 个数据库
  • JSON 文件中的 一级属性的数组值 好比是 集合
  • 数组中的对象好比是 文档
  • 对象中的属性有时也称之为 字段

3. 下载安装与启动

下载地址: **https://www.mongodb.com/try/download/community **
建议选择 zip 类型, 通用性更强
配置步骤如下:
1> 将压缩包移动到 C:\Program Files 下,然后解压
2> 创建 C:\data\db 目录,mongodb 会将数据默认保存在这个文件夹
3> 以 mongodb 中 bin 目录作为工作目录,启动命令行
4> 运行命令 mongod
【Node.js】(四)MongoDB、接口、会话控制_第2张图片
看到最后的 waiting for connections 则表明服务 已经启动成功
然后可以使用 mongo 命令连接本机的 mongodb 服务
【Node.js】(四)MongoDB、接口、会话控制_第3张图片

注意:
为了方便后续方便使用 mongod 命令,可以将 bin 目录配置到环境变量 Path 中
千万不要选中服务端窗口的内容 ,选中会停止服务,可以 敲回车 取消选中

4. 命令行交互

命令行交互一般是学习数据库的第一步,不过这些命令在后续用的比较少,所以大家了解即可

(1). 数据库命令

  1. 显示所有的数据库

show dbs

  1. 切换到指定的数据库,如果数据库不存在会自动创建数据库

use 数据库名

  1. 显示当前所在的数据库

db

  1. 删除当前数据库

use 库名
db.dropDatabase( )

(2). 集合命令

  1. 创建集合

db.createCollection(‘集合名称’)

  1. 显示当前数据库中的所有集合

show collections

  1. 删除某个集合

db.集合名.drop( )

  1. 重命名集合

db.集合名.renameCollection(‘newName’)

(3). 文档命令

  1. 插入文档

db.集合名.insert(文档对象);

  1. 查询文档

db.集合名.find(查询条件)

_id 是 mongodb 自动生成的唯一编号,用来唯一标识文档

  1. 更新文档

db.集合名.update(查询条件,新的文档)
db.集合名.update({name:‘张三’},{$set:{age:19}})

  1. 删除文档

db.集合名.remove(查询条件)

(4). 应用场景

  1. **新增 **
  • 用户注册
  • 发布视频
  • 发布商品
  • 发朋友圈
  • 发评论
  • 发微博
  • 发弹幕
  1. **删除 **
  • 删除评论
  • 删除商品
  • 删除文章
  • 删除视频
  • 删除微博
  1. 更新
  • 更新个人信息
  • 修改商品价格
  • 修改文章内容
  1. **查询 **
  • 商品列表
  • 视频列表
  • 朋友圈列表
  • 微博列表
  • 搜索功能

5. mongoose

Mongoose 是一个对象文档模型库,官网 http://www.mongoosejs.net/

(1). 使用流程

//1. 安装 mongoose
//2. 导入 mongoose
const mongoose = require('mongoose');
//3. 连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');
//4. 设置连接回调
//连接成功
mongoose.connection.on('open', () => {
    console.log('连接成功');
    //5. 创建文档结构对象
    let BookSchema = new mongoose.Schema({
        title: String,
        author: String,
        price: Number
    });
    //6. 创建文档模型对象
    let BookModel = mongoose.model('book', BookSchema);
    //7. 插入文档
    BookModel.create({
        title: '西游记',
        author: '吴承恩',
        price: 19.9
    }, (err, data) => {
        if (err) throw err;
        //输出 data 对象
        console.log(data);
        //8. 断开连接
        mongoose.disconnect();
    });
});
//连接出错
mongoose.connection.on('error', () => {
    console.log('连接出错~~');
})
//连接关闭
mongoose.connection.on('close', () => {
    console.log('连接关闭');
})

(2). 字段类型

类型 描述
String 字符串
Number 数字
Boolean 布尔值
Array 数组,也可以使用[ ]来标识
Date 日期
Buffer Buffer对象
Mixed 任意类型,需要使用 mongoose.Schema.Types.Mixed 指定
ObjectId 对象ID,需要使用 mongoose.Schema.Types.ObjectId 指定
Decimal128 高精度数字,需要使用 mongoose.Schema.Types.Decimal128 指定

(3). 字段值验证

Mongoose 有一些内建验证器,可以对字段值进行验证

  1. 必填项
title: {
  type: String,
  required: true // 设置必填项
},
  1. 默认值
author: {
  type: String,
  default: '匿名' // 默认值
},
  1. 枚举值
gender: {
  type: String,
  enum: ['男','女'] // 设置的值必须是数组中的
},
  1. 唯一值
username: {
  type: String,
  unique: true 
},

unique需要 重建集合 才能有效果
永远不要信息用户的输入

(4). CURD

数据库的基本操作包括四个,增加(create),删除(delete),修改(update),查(read)

  1. 增加

插入一条

SongModel.create({
    title: '给我一首歌的时间',
    author: 'Jay'
}, function (err, data) {
    //错误
    console.log(err);
    //插入后的数据对象
    console.log(data);
});

批量插入

//1.引入mongoose
const mongoose = require('mongoose');
//2.链接mongodb数据库 connect 连接
mongoose.connect('mongodb://127.0.0.1:27017/project');
//3.设置连接的回调
mongoose.connection.on('open', () => {
    //4.声明文档结构
    const PhoneSchema = new mongoose.Schema({
        brand: String,
        color: String,
        price: Number,
        tags: Array
    })
    //6.创建模型对象
    const PhoneModel = mongoose.model('phone', PhoneSchema);
    PhoneModel.insertMany([
        {
            brand: '华为',
            color: '灰色',
            price: 2399,
            tags: ['电量大', '屏幕大', '信号好']
        },
        {
            brand: '小米',
            color: '白色',
            price: 2099,
            tags: ['电量大', '屏幕大', '信号好']
        }
    ], (err, data) => {
        if (err) throw err;
        console.log('写入成功');
        mongoose.connection.close();
    })
})
  1. 删除

删除一条数据

SongModel.deleteOne({ _id: '5dd65f32be6401035cb5b1ed' }, function (err) {
    if (err) throw err;
    console.log('删除成功');
    mongoose.connection.close();
});

批量删除

SongModel.deleteMany({ author: 'Jay' }, function (err) {
    if (err) throw err;
    console.log('删除成功');
    mongoose.connection.close();
});
  1. 更新

更新一条数据

SongModel.updateOne({ author: 'JJ Lin' }, { author: '林俊杰' }, function (err) {
    if (err) throw err;
    mongoose.connection.close();
});

批量更新数据

SongModel.updateMany({ author: 'Leehom Wang' }, { author: '王力宏' }, function (err) {
    if (err) throw err;
    mongoose.connection.close();
});
  1. 查询

查询一条数据

SongModel.findOne({ author: '王力宏' }, function (err, data) {
    if (err) throw err;
    console.log(data);
    mongoose.connection.close();
});
//根据 id 查询数据
SongModel.findById('5dd662b5381fc316b44ce167', function (err, data) {
    if (err) throw err;
    console.log(data);
    mongoose.connection.close();
});

批量查询数据

//不加条件查询
SongModel.find(function (err, data) {
    if (err) throw err;
    console.log(data);
    mongoose.connection.close();
});
//加条件查询
SongModel.find({ author: '王力宏' }, function (err, data) {
    if (err) throw err;
    console.log(data);
    mongoose.connection.close();
});

(5). 条件控制

  1. 运算符

在 mongodb 不能 > < >= <= !== 等运算符,需要使用替代符号

  • 使用 $gt

  • < 使用 $lt
  • = 使用 $gte

  • <= 使用 $lte
  • !== 使用 $ne
 //id号比3大的所有的记录
db.studentsfind({ id: { $gt: 3 } }, (err, data) => {
    if (err) {
        console.log('提取失败!');
        return;
    }
    console.log(data);
})
  1. 逻辑运算

$or 逻辑或的情况

db.studentsfind({ $or: [{ age: 18 }, { age: 24 }] }, (err, data) => {
    if (err) {
        console.log('提取失败!');
        return;
    }
    console.log(data);
})

$and 逻辑与的情况

db.studentsfind({ $and: [{ age: { $lt: 20 } }, { age: { $gt: 15 } }] }, (err, data) => {
    if (err) {
        console.log('提取失败!');
        return;
    }
    console.log(data);
})
  1. 正则匹配

条件中可以直接使用 JS 的正则语法,通过正则可以进行模糊查询

db.studentsfind({ name: /imissyou/ }, (err, data) => {
    if (err) {
        console.log('提取失败!');
        return;
    }
    console.log(data);
})

或者写为

db.studentsfind({ name: new RegExp('imissyou') }, (err, data) => {
    if (err) {
        console.log('提取失败!');
        return;
    }
    console.log(data);
})

(6). 个性化读取

  1. 字段筛选
//0:不要的字段
//1:要的字段
BookModel.find().select({name:1,author:1}).exec((err,data)=>{
    if(err){
        console.log('查询失败!');
        return;
    }
    console.log(data);
})
//只返回每个字段的 name 和 author
  1. 数据排序
//sort 排序
//1: 升序
//-1:倒序
BookModel.find().sort({ hot: 1 }).exec((err, data) => {
    if (err) {
        console.log('查询失败!');
        return;
    }
    console.log(data);
})
//只返回每个字段的 name 和 author
  1. 数据截取
//skip  跳过
//limit 限定
BookModel.find().skip(10).limit(10).exec((err, data) => {
    if (err) {
        console.log('查询失败!');
        return;
    }
    console.log(data);
})

(7). 图形化管理工具

我们可以使用图形化的管理工具来对 Mongodb 进行交互,这里演示两个图形化工具

  • Robo 3T 免费 **https://github.com/Studio3T/robomongo/releases **
  • Navicat 收费 https://www.navicat.com.cn/

十二. 接口

1. 简介

接口是 前后端通信的桥梁
简单理解:一个接口就是 服务中的一个路由规则,根据请求响应结果
接口的英文单词是 API(Application Program Interface),所以有时也称之为API接口

2. 接口的组成

一个接口一般由如下几个部分组成

  • 请求方法
  • 接口地址(URL)
  • 请求参数
  • 响应结果

【Node.js】(四)MongoDB、接口、会话控制_第4张图片

3. RESTful API

RESTful API 是一种特殊风格的接口,主要特点有如下几个:

  • URL中的路径表示 资源,路径中不能有动词,例如 create,delete,update 等这些都不能用
  • 操作资源要与HTTP请求方法 对应
  • 操作结果要与HTTP 响应状态码对应

规则实例:

操作 请求类型 URL 返回
新增歌曲 POST /song 返回新生成的歌曲信息
删除歌曲 DELETE /song/10 返回一个空文档
修改歌曲 PUT /song/10 返回更新后的歌曲信息
修改歌曲 PATCH /song/10 返回更新后的歌曲信息
获取所有歌曲 GET /song 返回歌曲列表数组
获取单个歌曲 GET /song/10 返回单个歌曲信息

4. json-server

json-server本身是一个JS编写的工具包,可以快速搭建RESTful API服务
操作步骤:

  1. 全局安装 json-server

npm i -g json-server

  1. 创建JSON文件(db.json),编写基本结构
{
    "song": [
        { "id": 1, "name": "干杯", "singer": "五月天" },
        { "id": 2, "name": "当", "singer": "动力火车" },
        { "id": 3, "name": "不能说的秘密", "singer": "周杰伦" }
    ]
}
  1. 以 JSON 文件所在文件夹作为工作目录,执行如下命令

json-server --watch db.json

默认监听端口为3000

5. 接口测试工具

介绍几个接口测试工具

  • apipost **https://www.apipost.cn/ **(中文)
  • apifox **https://www.apifox.cn/ **(中文)
  • postman **https://www.postman.com/ **(英文)

十三. 会话控制

1. 介绍

所谓会话控制就是 对会话进行控制
HTTP 是一种无状态的协议,它没有办法区分多次的请求是否来自于同一个客户端, 无法区分用户
而产品中又大量存在的这样的需求,所以我们需要通过 会话控制 来解决该问题
常见的会话控制技术有三种:

  • cookie
  • session
  • token

2. cookie

cookie 是 HTTP 服务器发送到用户浏览器并保存在本地的一小块数据
cookie 是保存在浏览器端的一小块数据
cookie 是按照域名划分保存的
例子:

域名 cookie
www.baidu.com a=100;b=200
www.bilibili.com xid=1020abce121; hm=112411213
jd.com x=100;ocw=12414cce

(1). cookie的特点

浏览器向服务器发送请求时,会自动将 当前域名下 可用的 cookie 设置在请求头中,然后传递给服务器
这个请求头的名字也叫 cookie ,所以将 cookie 理解为一个 HTTP 的请求头也是可以的

(2). cookie的运行流程

填写账号和密码校验身份,校验通过后再发cookie
【Node.js】(四)MongoDB、接口、会话控制_第5张图片
有了cookie之后,后续向服务器发送请求时,就会自动携带cookie
【Node.js】(四)MongoDB、接口、会话控制_第6张图片

(3). 浏览器操作cookie

浏览器操作cookie的操作,使用相对较少

  • 禁用所有cookie
  • 删除cookie
  • 查看cookie

(4). cookie的代码操作

express中可以使用 cookie-parser 进行处理

const express = require('express');
//1. 安装 cookie-parser npm i cookie-parser
//2. 引入 cookieParser 包
const cookieParser = require('cookie-parser');
const app = express();
//3. 设置 cookieParser 中间件
app.use(cookieParser());
//4-1 设置 cookie
app.get('/set-cookie', (request, response) => {
    // 不带时效性
    response.cookie('username', 'wangwu');
    // 带时效性
    response.cookie('email', '[email protected]', { maxAge: 5 * 60 * 1000 });
    //响应
    response.send('Cookie的设置');
});
//4-2 读取 cookie
app.get('/get-cookie', (request, response) => {
    //读取 cookie
    console.log(request.cookies);
    //响应体
    response.send('Cookie的读取');
});
//4-3 删除cookie
app.get('/delete-cookie', (request, response) => {
    //删除
    response.clearCookie('username');
    //响应
    response.send('cookie 的清除');
});
//4. 启动服务
app.listen(3000, () => {
    console.log('服务已经启动....');
});

不同浏览器中的cookie是相互独立的,不共享

3. session

(1). session是什么

session是保存在 服务器端的一块儿数据,保存当前访问用户的相关信息

(2). session的作用

实现会话控制,可以识别用户的身份,快速获取当前用户的相关信息

(3). session运行流程

填写账号和密码校验身份,校验通过后创建 session信息,然后将session_id 的值通过响应头返回给浏览器
【Node.js】(四)MongoDB、接口、会话控制_第7张图片
有了cookie,下次发送请求时就会自动携带cookie,服务器通过cookie中的session_id的值确定用户的身份
【Node.js】(四)MongoDB、接口、会话控制_第8张图片

(4). session的代码操作

express中可以使用 express-session 对session进行操作

const express = require('express');
//1. 安装包 npm i express-session connect-mongo
//2. 引入 express-session connect-mongo
const session = require("express-session");
const MongoStore = require('connect-mongo');
const app = express();
//3. 设置 session 的中间件
app.use(session({
    name: 'sid', //设置cookie的name,默认值是:connect.sid
    secret: 'atguigu', //参与加密的字符串(又称签名)
    saveUninitialized: false, //是否为每次请求都设置一个cookie用来存储session的id
    resave: true, //是否在每次请求时重新保存session
    store: MongoStore.create({
        mongoUrl: 'mongodb://127.0.0.1:27017/project' //数据库的连接配置
    }),
    cookie: {
        httpOnly: true, // 开启后前端无法通过 JS 操作
        maxAge: 1000 * 300 // 这一条 是控制 sessionID 的过期时间的!!!
    },
}))
//创建 session
app.get('/login', (req, res) => {
    //设置session
    req.session.username = 'zhangsan';
    req.session.email = '[email protected]'
    res.send('登录成功');
})
//获取 session
app.get('/home', (req, res) => {
    console.log('session的信息');
    console.log(req.session.username);
    if (req.session.username) {
        res.send(`你好 ${req.session.username}`);
    } else {
        res.send('登录 注册');
    }
})
//销毁 session
app.get('/logout', (req, res) => {
    //销毁session
    // res.send('设置session');
    req.session.destroy(() => {
        res.send('成功退出');
    });
});
app.listen(3000, () => {
    console.log('服务已经启动, 端口 ' + 3000 + ' 监听中...');
});

4. session 和 cookie 的区别

cookie 和 session 的区别主要有如下几点:

  1. 存在的位置
  • cookie:浏览器端
  • session:服务端
  1. 安全性
  • cookie 是以明文的方式存放在客户端的,安全性相对较低
  • session 存放于服务器中,所以安全性 相对 较好
  1. 网络传输量
  • cookie 设置内容过多会增大报文体积, 会影响传输效率
  • session 数据存储在服务器,只是通过 cookie 传递 id,所以不影响传输效率
  1. 存储限制
  • 浏览器限制单个 cookie 保存的数据不能超过 4K ,且单个域名下的存储数量也有限制
  • session 数据存储在服务器中,所以没有这些限制

5. token

(1). token 是什么

token 是服务端生成并返回给 HTTP 客户端的一串加密字符串, token 中保存着 用户信息

(2). token 的作用

实现会话控制,可以识别用户的身份,主要用于移动端 APP

(3). token 的工作流程

填写账号和密码校验身份,校验通过后响应token,token一般是在响应体中返回给客户端
【Node.js】(四)MongoDB、接口、会话控制_第9张图片
后续发送请求时,需要手动将token添加到请求报文中,一般是放在请求头中
【Node.js】(四)MongoDB、接口、会话控制_第10张图片

(4). token的特点

  1. 服务端压力更小 (数据存储在客户端 )
  • 相对更安全
  1. 数据加密
  • 可以避免 CSRF(跨站请求伪造)
  1. 扩展性更强
  • 服务间可以共享
  • 增加服务节点更简单

(5). JWT

JWT(JSON Web Token )是目前最流行的跨域认证解决方案,可用于基于 token 的身份验证
JWT 使 token 的生成与校验更规范
我们可以使用 jsonwebtoken 包 来操作 token

//导入 jsonwebtokan
const jwt = require('jsonwebtoken');
//创建 token
// jwt.sign(数据, 加密字符串, 配置对象)
let token = jwt.sign({
    username: 'zhangsan'
}, 'atguigu', {
    expiresIn: 60 //单位是 秒
})
//解析 token
jwt.verify(token, 'atguigu', (err, data) => {
    if (err) {
        console.log('校验失败~~');
        return
    }
    console.log(data);
})

你可能感兴趣的:(mongodb,node.js,数据库)