Mongoose简介

明确需求

为什么学数据库,因为要存放项目/网站数据
思考:实战中也像我们刚刚那样敲命令?
回答:非也,而是通过程序来
思考:如何实现呢?
回答: mongoose

是什么

是node中提供操作MongoDB的模块

能干吗

能够通过node语法实现MongoDB数据库增删改查
从而实现用node写程序来管理MongoDB数据库

在那下

1
2
3
npm i mongoose
#或者
yarn add mongoose

schema

英文网: http://mongoosejs.com

中文网: http://mongoosejs.net/

作用:用来约束MongoDB文档数据(哪些字段必须,哪些字段可选的)

model

一个模型对应一个集合

后面我们通过模型来管理集合中的数据

小总结

为什么要学习mongoose: 通过命令管理mongodb麻烦,通过程序管理

是什么: 就是node中的一个模块

能干吗: 让node借助这个模块实现管理mongodb的程序

去哪下: 通过npm或yarn命令来安装

mongoose核心概念

schema 约束字段/列数据
model 模型对应集合后期用它来实现数据增删改查

Mongoose使用

安装

步骤1: 创建api目录

步骤2: 在api目录下安装mongoose模块

语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 一、导入模块
const mongoose = require("mongoose");
// 二、连接数据库
const db = mongoose.createConnection(
"mongodb://shop2:shop2@localhost:27017/shop",
{ useNewUrlParser: true, useUnifiedTopology: true },
(err) => {
if (err) {
console.log("---------------------------------------");
console.log("数据库连接失败:", err);
console.log("---------------------------------------");
return;
}
console.log("数据库连接成功");
}
);

// 三、设置数据模型(声明是哪个集合,限制字段个数和字段类型)
const model = db.model("api", {
uname: { type: String, default: "username" },
pwd: String,
age: { type: Number },
sex: { type: String },
});

// 四、创建实例操作(CURD)
// 增
const insertobj = new mode1(数据对象)
// 方法1: insertobj.save((err) => db.close())
// 方法2(推荐)
insertObj.save()
.then(res =>{
return res
})
.catch(err => {
console.log('插入失败'+err)
return false
})

// 删
// 方法1: model.remove/deleteone/deleteMany(条件对象,(err) => db.close())
// 方法2(推荐)
model.deleteOne(条件对象)
.then(res => {
return resdeletedCount
})
.catch(err => {
console.log('删除失败'+ err)
return false
})

// 改
//方法1: model.update/updateOne/updateMany(条件对象,数据对象,(err) => db.close())
// 方法2(推荐)
mode1.updateOne(条件对象,数据对象)
.then(res => {
return res.nModified
})
.catch(err => {
console.1og('修改失败'+err)
return false
})

// 查
// 方法1: model.find/findOne(条件对象,要显示的字段数据对象,(err,result)=> db.close())
// 方法2(推荐)
model.find(条件对象)
.then((res) => {
console.log(res);
return res;
})
.catch((err) => {
console.log(err);
return false;
});

练习

1
2
3
4
5
6
const insertObj = new model({
uname: "张三",
pwd: "123",
age: 18,
sex: "man",
});

c.js

1
2
3
4
5
6
7
8
9
10
// 增
insertObj.save()
.then((res) => {
console.log(res);
return res;
})
.catch((err) => {
console.log("插入失败" + err);
return false;
});

r.js

1
2
3
4
5
6
7
8
9
10
11
// 查
model.find({})
.then((res) => {
console.log(res);
db.close()
return res;
})
.catch((err) => {
console.log(err);
return false;
});

分页

1
2
3
4
5
6
7
8
9
10
model.find({}).skip(1).limit(1)
.then((res) => {
console.log(res);
db.close()
return res;
})
.catch((err) => {
console.log(err);
return false;
});

小总结

安装: yarn add mongoose 或者 npm i mongoose
使用: http://mongoosejs.nethttp://mongoosejs.com

接口概念

什么是接口

就是一个文件(js/json/php),主要响应JSON数据(操作方便,体积小)或XML数据

1
2
3
4
5
6
7
8
9
10
{
status : 1/0,
msg:'提示信息'
}
--------
<xml>
<status>1/0</status>
<msg>提示信息</msg>
...
</xm1>
  • 多学一招:只要响应json数据所有语言都可以操作,例如ios/Android等

  • 推荐

    1
    2
    3
    4
    5
    6
    7
    {
    meta: {
    msg:提示信息
    status:状态码(200/201/301/302/400/401/403/404/500)
    }
    data:数据
    }

能干吗

数据角度:让我们的项目静态/固定数据动态(也就是让项目数据来源于数据库

功能角度:短信接口、幽默笑话接口、天气接口、股票接等

去哪下(找)

  • 方案1: 通过node/go/java/php/asp等语言去开发
  • 方法2: 使用第三方接口

小总结

为什么要有接口: 一次编写,多次/随时接入(好处:减少后端工作量方便后期维护

什么是接口: 就是一个文件,但是你必须返回json或xml数据

接口能干吗: 1-数据角度:页面数据动态,2-功能角度:短信接口、人脸识别接口

去哪下: 1-自己写,2-去第三方网站找

接口开发规范(Restful API)

明确需求

思考:接口可能是一个人开发,也可能多人开发,如何保证大家的编写规范一样

商品模块/goods/getlndexget
订单模块lorderlindex
post
用户模块/user

发现:上述这种case项目没有统一开发规则

问题: 后期维护麻烦

回答: 通过目前比较火的Restful API思想/架构

是什么&好处

  • 说明:RESTful是目前最流行的一种互联网软件架构(思想)

  • 作用:声明/提供了接口设计原则和约束条件(一个范围)

  • 相关:

    后端将资源发布到URL上->前端通过URL访问资源->并通过HTTP动词表示要对资源进行的操作
    后端定义接口->前端请求接口->HTTP动词表名操作目的(get获取post新建put更新等)

  • 举栗

    列表页: 访问-/模块名 (get)
    详情页: 访问-/模块名/编号 (get)
    添加页: 访问-/模块名/create (get)
    处理: 访问-/模块名 (post)
    修改页: 访问-/模块名/编号/edit (get)
    处理: 访问-/模块名/编号 (put)
    删除: 访问-/模块名/编号 (delete)
    HTTP动词: get、post、put、delete

  • 好处: 统一开发规范,便与团队协作开发

标准的RESTful架构/思想/规则需要做到

1
2
3
4
5
订单模块
/order get
/order post
/order/编号 put
/order/编号 delete
  • 项目所有模块有统一的标准
  • 看Url就知道要操作的资源是什么(也就是哪个模块)
  • 看Http Method就知道操作动作是什么,是添加(post)还是删除(delete)
  • 看Http Status Code就知道操作结果如何,是成功(200)还是内部错误(500)

小总结

什么是restful api: 是一个架构或思想

作用: 声明了接口设计原则和约束条件

好处: 统一开发规范,便于团队协作开发

接口测试工具(Postman&insomnia)

概念

  • 什么是Postman:就是一个工具
  • 作用:模拟HTTP请求,测试接口,查看接口返回数据
  • 官网: www.getpostman.com

下载安装

百度安装教程。。。

使用

百度使用教程。。。

使用postman请求接口 https://jsonview.com/example.json

实战教学管理系统学生模块接口开发

express简介

  • 是什么:基于nodejs开发的一个框架(原理基于node内置http模块封装)
  • 好处:加快项目开发,便于团队协作

express使用

步骤1: 下载(yarn add express 或者 npm i express

1
2
3
yarn add express 
# 或者
npm i express

步骤2: 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1.引入express模块
const express = require("express")

// 2.创建app对象,通过语法express()底层原理http模块的createServer
const app = express()
const port = 3000

// 3.路由,语法 app.HTTP请求方式(路径,回调函数)
app.get("/",(req,res)=>{
res.send("Hello world!")
})

// 4.启动服务监听端口
app.listen(port,()=>{
console.log("端口"+ port + "启动");
})

学生添加接口

步骤1: 定义路由/stu post

1
2
3
4
// http.js
// 学生添加
const stuController = require(process.cwd()+"/controller/stu")
app.post("/stu",stuController.create)
1
2
3
4
5
6
7
8
// controller/stu.js
const create = (req,res)=>{
res.send("学生接口")
}

module.exports = {
create
}

步骤2:响应任意json数据

使用PostMan向 https://localhost:3000/stu 发起post就行

步骤3:定义stu模块,定义创建数据的方法

需要安装 npm i bodyparser进行解析

1
2
3
4
// 它用于解析客户端请求的body中的内容,内部使用JSON编码处理,url编码处理以及对于文件的上传处理
const bodyparser = require("body-parser")
app.use(bodyparser.urlencoded({extended:true}))
app.use(bodyparser.json())

定义连接数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// models/stu.js
// 一、导入模块
const mongoose = require("mongoose");

// 二、连接数据库
const db = mongoose.createConnection(
"mongodb://shop2:shop2@localhost:27017/shop",
{ useNewUrlParser: true, useUnifiedTopology: true },
(err) => {
if (err) {
console.log("---------------------------------------");
console.log("数据库连接失败:", err);
console.log("---------------------------------------");
return;
}
console.log("数据库连接成功");
}
);

// 三、设置数据模型(声明是哪个集合,限制字段个数和字段类型)
const model = db.model("stu", {
uname: { type: String, default: "神龙教主" },
pwd: String,
age: { type: Number },
sex: { type: String },
});

const createModel = (postData) => {
insertObj = new model(postData);
return insertObj
.save()
.then((res) => {
return res;
})
.catch((err) => {
console.log("插入失败"+err);
return false;
});
};

// 四、方法
module.exports = { createModel };

步骤4:调用stu模型创建数据的方法,返回结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// controller/stu.js
// 导入模型
const { createModel } = require(process.cwd() + "/models/stu");

//定义处理方法
const create = async (req, res) => {
// res.send("this is stu create");
// 1.接收参数
let postData = req.body;
// 2.过滤(忽略
// 3. 操作数据库
let rs = await createModel(postData);
// 4. 判断返回
if (rs) {
res.send({
meta: {
state: 200,
msg: "添加成功",
},
data: null,
});
} else {
res.send({
meta: {
state: 500,
msg: "添加失败",
},
data: null,
});
}
};

module.exports = {
create
}

学生列表接口

步骤1: 定义路由/stu get

1
2
// http.js
app.get("/stu",stuController.index)

步骤2: 响应任意json数据

步骤3: 修改stu模型,增加查询方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// models/stu.js
// 查询数据
const listModel = () => {
return model
.find()
.then((res) => {
console.log(res);
return res;
})
.catch((err) => {
console.log(err);
return null;
});
};

// 四、方法
module.exports = { listModel };

步骤4: 修改控制,调用模型返回数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const { listModel } = require(process.cwd() + "/models/stu");

const index = (req, res) => {
listModel().then((rs) => {
if (rs) {
res.send({
meta: {
state: 200,
msg: "查询成功",
},
data: rs,
});
} else {
res.send({
meta: {
state: 500,
msg: "查询失败",
},
data: null,
});
}
});
};

module.exports = {
index
}

学生列表接口分页

步骤1:修改控制器接口请求参数(get)

1
app.get("/stu",stuController.index)

步骤2:传递给模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const index = (req, res) => {
let getData = req.query;
let pagesize = parseInt(getData.pagesize);
let skip = (parseInt(getData.pageno) - 1) * pagesize;
listModle(skip, pagesize).then((rs) => {
if (rs) {
res.send({
meta: {
state: 200,
msg: "查询成功",
},
data: rs,
});
} else {
res.send({
meta: {
state: 500,
msg: "查询失败",
},
data: null,
});
}
});
};

步骤3:模型增加skip和limit即可

1
2
3
4
5
6
7
8
9
10
11
12
// 查询数据
const listModle = (skip, limit) => {
return model.find().skip(skip).limit(limit)
.then((res) => {
console.log(res);
return res;
})
.catch((err) => {
console.log(err);
return null;
});
};

实战接口文档开发apiDoc

明确需求

实战开发中后端会开发很多很多接口

每个接口呢都有大量的参数

思考:前端如果知道有哪些接口并且每个接口有几个参数?

回答:通过接口文档

思考:接口文档自己写还是怎么样?

回答:有很多,本接口主要是通过该apiDoc来生成

是什么

就是nodejs中的一个模块

能干吗

通过这个模块可以快速生成接口文档

前提写接口的时候把注释加上

去哪下

https://apidocjs.com/

使用

  1. 安装模块(仅一次)

    1
    npm install apidoc -g
  2. 在项目根目录创建 apidoc.json 文件(仅一次)

    1
    2
    3
    4
    5
    6
    7
    {
    "name": "example",
    "version": "0.1.0",
    "description": "apiDoc basic example",
    "title": "Custom apiDoc browser title",
    "url" : "https://api.github.com/v1"
    }

    例如:

    1
    2
    3
    4
    5
    6
    7
    {
    "name": "教学管理系统接口文档",
    "version": "1.0.0",
    "description": "一个非常NB的接口文档",
    "title": "Custom apiDoc browser title",
    "url" : "http://localhost:3000"
    }
  3. 写接口注释(N 次)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
    * @api {get} /user/:id Request User information
    * @apiName GetUser
    * @apiGroup User
    *
    * @apiParam {Number} id Users unique ID.
    *
    * @apiSuccess {String} firstname Firstname of the User.
    * @apiSuccess {String} lastname Lastname of the User.
    */

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * @api {get} /stu 学生模块列表
    * @apiName Add
    * @apiGroup Stu
    *
    * @apiParam {Number} pageno 当前页
    * @apiParam {Number} pagesize 每页显示条数
    *
    * @apiSuccess {String} meta 状态码&提示信息
    * @apiSuccess {String} data 数据
    */
  4. 生成接口文档(N 次)

    1
    apidoc -i ./接口注释目录 -o ./接口文档存放目录