欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > Mongoose下载安装与使用

Mongoose下载安装与使用

2025/6/22 12:36:05 来源:https://blog.csdn.net/Y1914960928/article/details/148735954  浏览:    关键词:Mongoose下载安装与使用

一、Mongoose:对象文档模型库

1、官网:

https://mongoosejs.net/

2、作用:

方便使用代码操作 mongodb 数据库

3、安装 Mongoose

npm i mongoose
在这里插入图片描述

4、连接数据库:

终端要一直运行服务端程序!!!

① 引用 mongoose 模块:

const mongoose = require('mongoose')

② 数据库建立连接:

端口号默认是 27017

(1)创建默认全局连接:

mongoose.connect('mongodb://域名:端口号/数据库名称')

(2)创建独立连接实例:

mongoose.createConnection(mongodb://域名:端口号/数据库名称')

③ 数据库关闭连接:

(1)独立连接关闭:

实例对象.close()

(2)全局连接关闭(默认):

mongoose.disconnect() 或者 mongoose.close()

④ 访问数据库连接实例:

(1)独立连接对象:

mongoose.createConnection() 函数调用后,返回新的连接对象

(2)全局连接对象(默认):

存储在 mongoose.connection

⑤ 设置数据库连接回调:

(1)连接成功的回调:
a、 once:回调函数只会在第一次连接成功时执行

适合一次性操作(如初始化)

db.once('open', () => {console.log('首次连接成功');
});
b、 on:回调函数每次连接成功都会执行

适合错误处理(需要持续监控)、连接状态变化(需持久响应)

db.on('open', () => {console.log('数据库连接已建立(每次重连都会触发)');
});
(2)连接失败的回调:

先执行 连接断开 的回调,再执行 连接失败 的回调

db.on('error', () => {console.log('数据库连接失败')
})
(3)连接断开的回调:
db.on('disconnected', () => {console.log('数据库断开连接')
})
(4)连接关闭的回调:

先执行 连接断开 的回调,再执行 连接关闭 的回调

db.on('close', () => {console.log('数据库关闭连接')
})

⑤ 完整练习代码:

// 1、引入mongoose
const mongoose = require('mongoose')// 2、全局连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 测试数据库连接失败
// mongoose.connect('mongodb://127.0.0.1:27018/a')
// 3、获取全局连接的实例
const db = mongoose.connection;
// 获取独立连接的实例
// let db = mongoose.createConnection('mongodb://127.0.0.1:27017/a')
// 4、设置回调
db.once('open', () => {console.log('数据库连接成功')
})db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})// 数据库关闭连接
// setTimeout(() => {
//     db.close()
// }, 5000)

5、文档的字段类型:

① 字符串: String

② 数字: Number

③ 布尔值: Boolean

④ 数组: Array 或者 []

⑤ 日期: Date

Buffer对象: Buffer

⑦ 任意类型: mongoose.Schema.Types.Mixed

⑧ 对象 IDmongoose.Schema.Types.ObjectId

主要用于定义外键,即将另外一个文档的 id 存到 本文档中,进行联合查询

⑨ 高精度数字: mongoose.Schema.Types.Decimal128

6、验证器:

文档属性值(字段值)的验证

① 设置必填项:required: true

② 设置默认值:default: 数据

③ 设置枚举:enum: [数据1, 数据2,...]

属性值(字段值)必须是当前枚举中的数据

④ 唯一值:unique: true

如果在已有的集合中进行设置,则无用;需要新建集合才生效

属性值不允许重复!必须是唯一的!

⑤ 完整语法:

属性名:{type: 属性值的类型,验证器
}

⑥ 以 新增文档 为例的完整代码:

// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']},grade: {type: String,unique: true},hobby: Array})let person = mongoose.model('persons', personType)// 使用 `Promise` 语法新增数据person.create({name: 'red',age: undefined,sex: '男',grade:'大二',hobby: ['吃饭']}).then((data) => {// 新增后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('新增数据失败',err)})console.log('数据库连接成功')
})db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

7、文档的操作:

在数据库 连接成功的回调函数 中编写代码

① 创建文档的结构对象:

文档的结构:集合中文档的属性及属性值的类型

let 文档结构对象名 = new mongoose.Schema({属性名1: 属性值的类型1,属性名2: 属性值的类型2,...
})

② 创建模型对象:

模型对象:对文档进行封装后,可以操作的对象

let 模型对象名 = mongoose.model(集合名,文档的结构对象名)

③ 创建文档:

如果属性名写错了,则忽略该属性

(1)使用 async/await 语法新增数据:
async function 新增文档的函数名(模型对象名) {try {const user = await 模型对象名.create(数据对象);// 新增后的文档对象console.log(user);} catch (err) {console.log('新增数据失败',err)}
}
(2)使用 Promise 语法新增数据:
模型对象名.create(数据对象).then((data) => {// 新增后的文档对象console.log(data);
}).catch((err) => {console.log('新增数据失败',err)
})
(3)完整的代码:
// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: String,age: Number,sex: String,hobby: Array})let person = mongoose.model('persons', personType)// 新增数据// createData(person)// 使用 `Promise` 语法新增数据person.create({name: 'lisi',age: 23,sex: '女',hobby: ['打球']}).then((data) => {// 新增后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('新增数据失败',err)})console.log('数据库连接成功')
})
// 使用 `async/await` 语法新增数据
async function createData(person) {try {const user = await person.create({name: 'zhangsan',age: 20,sex: '男',hobby: ['吃饭', '睡觉', '打豆豆']});// 新增后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('新增数据失败',err)}
}db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

④ 删除文档:

(1)使用 async/await 语法删除数据:
a、删除一个文档(匹配的第一个):
async function deleteData(person) {try {const user = await person.deleteOne(删除的条件);// 删除后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('删除数据失败',err)}
}
b、删除多个文档(匹配的所有的):
async function deleteData(person) {try {const user = await person.deleteMany(删除的条件);// 删除后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('删除数据失败',err)}
}
(2)使用 Promise 语法删除数据:
a、删除一个文档(匹配的第一个):
模型对象名.deleteOne(删除条件).then((data) => {// 删除后的文档对象console.log(data);
}).catch((err) => {console.log('删除数据失败',err)
})
b、删除多个文档(匹配的所有的):
模型对象名.deleteMany(删除条件).then((data) => {// 删除后的文档对象console.log(data);
}).catch((err) => {console.log('删除数据失败',err)
})
(3)完整的代码:
// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']},grade: {type: String,unique: true},hobby: Array})let person = mongoose.model('persons', personType)// 删除数据deleteData(person)// 使用 `Promise` 语法删除数据// 删除一条// person.deleteOne({age: 0}).then((data) => {// 删除多条// person.deleteMany({age: 25}).then((data) => {//     // 删除后的文档对象//     console.log(data);//     // 断开数据库连接。项目运行过程中,不会添加该代码//     mongoose.disconnect()// }).catch((err) => {//     console.log('删除数据失败',err)// })console.log('数据库连接成功')
})
// 使用 `async/await` 语法删除数据
async function deleteData(person) {try {// 删除一条// const user = await person.deleteOne({age: 0});// 删除多条const user = await person.deleteMany({age: 25});// 删除后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('删除数据失败',err)}
}db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

⑤ 更新文档:

(1)使用 async/await 语法更新数据:
a、更新一个文档(匹配的第一个):
async function updateData(person) {try {const user = await person.updateOne(查找数据的条件, 新数据);// 更新后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('更新数据失败',err)}
}
b、更新多个文档(匹配的所有的):
async function updateData(person) {try {const user = await person.updateMany(查找数据的条件, 新数据);// 更新后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('更新数据失败',err)}
}
(2)使用 Promise 语法更新数据:
a、更新一个文档(匹配的第一个):
模型对象名.updateOne(查找数据的条件, 新数据).then((data) => {// 更新后的文档对象console.log(data);
}).catch((err) => {console.log('更新数据失败',err)
})
b、更新多个文档(匹配的所有的):
模型对象名.updateMany(查找数据的条件, 新数据).then((data) => {// 更新后的文档对象console.log(data);
}).catch((err) => {console.log('更新数据失败',err)
})
(3)完整的代码:
// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']},grade: {type: String,unique: true},hobby: Array})let person = mongoose.model('persons', personType)// 更新数据// updateData(person)// 使用 `Promise` 语法更新数据// 更新一条// person.updateOne({sex: '女'}, {name: '小绿'}).then((data) => {// 更新多条person.updateMany({sex: '男'}, {name: '小哥'}).then((data) => {// 更新后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('更新数据失败',err)})console.log('数据库连接成功')
})
// 使用 `async/await` 语法更新数据
async function updateData(person) {try {// 更新一条// const user = await person.updateOne({sex: '女'}, {name: '小红'});// 更新多条const user = await person.updateMany({sex: '男'}, {name: '小华'});// 更新后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('更新数据失败',err)}
}db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

⑥ 查询文档:

(1)使用 async/await 语法查询数据:
a、查询一个文档(匹配的第一个):
async function findData(person) {try {const user = await person.findOne(查询的条件);// 查询后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('查询数据失败',err)}
}
b、根据_Id查询文档(_idmongoose自动生成的):
async function findData(person) {try {const user = await person.findById(_id的值);// 查询后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('查询数据失败',err)}
}
c、查询匹配的多个文档(匹配的所有的):
async function findData(person) {try {const user = await person.find(查询的条件);// 查询后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('查询数据失败',err)}
}
d、查询当前集合下的所有文档:
async function findData(person) {try {const user = await person.find();// 查询后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('查询数据失败',err)}
}
(2)使用 Promise 语法查询数据:
a、查询一个文档(匹配的第一个):
模型对象名.findOne(查找数据的条件).then((data) => {// 查找的文档对象console.log(data);
}).catch((err) => {console.log('查找数据失败',err)
})
b、根据_Id查询文档(_idmongoose自动生成的):
模型对象名.findById(_id的值).then((data) => {// 查找的文档对象console.log(data);
}).catch((err) => {console.log('查找数据失败',err)
})
c、查询匹配的多个文档(匹配的所有的):
模型对象名.find(_查询的条件).then((data) => {// 查找的文档对象console.log(data);
}).catch((err) => {console.log('查找数据失败',err)
})
d、查询当前集合下的所有文档:
模型对象名.find().then((data) => {// 查找的文档对象console.log(data);
}).catch((err) => {console.log('查找数据失败',err)
})
(3)完整的代码:
// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']},grade: {type: String,unique: true},hobby: Array})let person = mongoose.model('persons', personType)// 查询数据// findData(person)// 使用 `Promise` 语法查询数据// 查询一条// person.findOne({sex: '女'}).then((data) => {// 根据id查询// person.findById('68491e76d4d339bb1ac779a9').then((data) => {// 查询多条// person.find({sex: '男'}).then((data) => {// 查询所有数据person.find().then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('查询数据失败',err)})console.log('数据库连接成功')
})
// 使用 `async/await` 语法查询数据
async function findData(person) {try {// 查询一条// const user = await person.findOne({sex: '女'});// 根据id查询// const user = await person.findById('68491e76d4d339bb1ac779a9');// 查询多条// const user = await person.find({sex: '男'});// 查询所有数据const user = await person.find();// 查询后的文档对象console.log(user);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()} catch (err) {console.log('查询数据失败',err)}
}db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

8、条件控制:

① 运算符:

(1)大于:$gt
(2)小于:$lt
(3)大于等于:$gte
(4)小于等于:$lte
(5)不恒等于:$ne
(6)使用语法:
{字段名: {运算符: 数值}}
(7)完整的代码:

查询 age大于等于18, age小于等于20 的数据

// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']},grade: {type: String,unique: true},hobby: Array})let person = mongoose.model('persons', personType)// 使用 `Promise` 语法查询数据person.find({age: {$gte: 18,$lte: 20}}).then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('查询数据失败',err)})console.log('数据库连接成功')
})db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

② 逻辑运算:

(1)逻辑或:$or
(2)逻辑与:$and
(3)使用语法:
{逻辑运算符: [条件1, 条件2, ...]}
(4)完整代码:

查询 age大于等于18,age小于等于20;name是 小绿或者小哥 的数据

// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']},grade: {type: String,unique: true},hobby: Array})let person = mongoose.model('persons', personType)// 使用 `Promise` 语法查询数据person.find({age: {$gte: 18,$lte: 20},$or: [{name: '小绿'}, {name: '小哥'}]}).then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('查询数据失败',err)})console.log('数据库连接成功')
})db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

③ 正则匹配:

(1)使用语法:
a、字面量形式:
{字段名: /正则语法/}
b、对象形式:
{字段名: new RegExp(正则语法)}
(2)完整代码:

查询 age大于等于18,age小于等于20;name是 小绿或者小哥;grade的值带有 二 的数据

// 1、引入mongoose
const mongoose = require('mongoose')
// 2、连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/a')
// 3、获取连接的实例
const db = mongoose.connection;
// 4、设置回调
db.once('open', () => {let personType = new mongoose.Schema({name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']},grade: {type: String,unique: true},hobby: Array})let person = mongoose.model('persons', personType)// 使用 `Promise` 语法查询数据person.find({age: {$gte: 18,$lte: 20},$or: [{name: 'orange'}, {name: '小哥'}],// grade: /二/,grade: new RegExp('二')}).then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('查询数据失败',err)})console.log('数据库连接成功')
})db.on('error', () => {console.log('数据库连接失败')
})
db.on('disconnected', () => {console.log('数据库断开连接')
})
db.on('close', () => {console.log('数据库关闭连接')
})

9、个性化读取:

exec()函数:用于精确的控制查询的执行

① 字段筛选:select({字段名: 取值})

取值0:不需要的字段;取值1:需要的字段

如果使用字段筛选,_id默认是需要的字段,其它字段默认是不需要的字段
示例:返回当前集合中的name列表

person.find().select({name: 1, _id: 0}).then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()
}).catch((err) => {console.log('查询数据失败',err)
})

② 数据排序:sort({字段名: 取值})

取值1:升序;取值-1:倒序

如果使用字段筛选,_id默认是需要的字段,其它字段默认是不需要的字段
示例:根据age进行从小到大排序,然后返回当前集合中的name列表

// 将查询和构建分离
letnames = person.find().select({name: 1, _id: 0})
names.sort({age: 1})
names.exec().then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()
}).catch((err) => {console.log('查询数据失败',err)
})

③ 数据截取:

(1)限制返回数据的个数:limit(数量)

示例:根据age进行从小到大排序,然后返回当前集合中的前3位的name列表

person.find().select({name: 1, _id: 0}).sort({age: 1}).limit(3).exec().then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('查询数据失败',err)})console.log('数据库连接成功')
(2)限制数据从第几个数据开始返回:skip(数量)

示例:根据age进行从小到大排序,然后跳过第一位,返回当前集合中的前3位的name列表

person.find().select({name: 1, _id: 0}).sort({age: 1}).skip(1).limit(3).then((data) => {// 查询后的文档对象console.log(data);// 断开数据库连接。项目运行过程中,不会添加该代码mongoose.disconnect()}).catch((err) => {console.log('查询数据失败',err)})

10、代码模块化(CommonJs规范):

在这里插入图片描述

初始的 index.js文件:初始化

// 引入数据库连接处理
const db = require('./db/index.js')
const func = require('./model/index.js')
db.dbFunc(func.createPerson)

数据库 index.js文件:数据库连接操作

// 数据库连接处理
const mongoose = require('mongoose')
const DBData = {IP: '127.0.0.1',PORT: '27017',DBNAME: 'a'
}
mongoose.connect(`mongodb://${DBData.IP}:${DBData.PORT}/${DBData.DBNAME}`)
const db = mongoose.connection;let dbFunc = function(success, error) {if (typeof error !== 'function') {error = () => { console.log('数据库连接失败') }}db.once('open', () => {success()})db.on('error', () => {error()})db.on('disconnected', () => {console.log('数据库断开连接')})db.on('close', () => {console.log('数据库关闭连接')})
}
module.exports = {dbFunc,DBData
}

模型库 schema.js文件:定义结构对象

// 结构对象
const personType = {name: {type: String,required: true},age: {type: Number,default: 18,},sex: {type: String,enum: ['男', '女']}
}const bookType = {title: {type: String,},author: {type: String,default: '匿名',},
}
module.exports = {personType,bookType
}

模型库 index.js文件:数据库连接成功的操作

let mongoose = require('mongoose')
const {personType} = require('./schema.js')
const createPerson = function() {let personObj = new mongoose.Schema(personType)let person = mongoose.model('persons', personObj)person.create({name: 'purple',age: 25,sex: '女'}).then((data) => {console.log('新增的数据', data)mongoose.disconnect()}).catch((err) => {console.log('新增数据失败',err)})
}
module.exports = {createPerson
}

11、项目练习(自用):将本地数据库改为远程数据库

将 Express框架使用 中的 第七部分练习项目 进行修改

在这里插入图片描述
别忘记启动数据库服务器,该服务器与业务的服务器是两个东西!

① 进行数据库连接:

将原本的服务器代码封装为一个初始化的函数,用于进行数据库的连接(数据库连接成功后,才允许进行业务的服务连接)

www.js文件代码如下:

// 引入数据库连接处理
const db = require('../db/index.js')
// 服务器初始化操作
let init = function() {var app = require('../app');var debug = require('debug')('13:server');var http = require('http');/*** Get port from environment and store in Express.*/var port = normalizePort(process.env.PORT || '3000');app.set('port', port);/*** Create HTTP server.*/var server = http.createServer(app);/*** Listen on provided port, on all network interfaces.*/server.listen(port);server.on('error', onError);server.on('listening', onListening);/*** Normalize a port into a number, string, or false.*/function normalizePort(val) {var port = parseInt(val, 10);if (isNaN(port)) {// named pipereturn val;}if (port >= 0) {// port numberreturn port;}return false;}/*** Event listener for HTTP server "error" event.*/function onError(error) {if (error.syscall !== 'listen') {throw error;}var bind = typeof port === 'string'? 'Pipe ' + port: 'Port ' + port;// handle specific listen errors with friendly messagesswitch (error.code) {case 'EACCES':console.error(bind + ' requires elevated privileges');process.exit(1);break;case 'EADDRINUSE':console.error(bind + ' is already in use');process.exit(1);break;default:throw error;}}/*** Event listener for HTTP server "listening" event.*/function onListening() {var addr = server.address();var bind = typeof addr === 'string'? 'pipe ' + addr: 'port ' + addr.port;debug('Listening on ' + bind);}
}
db.dbFunc(() => {// 先进行数据库的连接,然后再启动服务器init()
})

② 进行结构对象的定义:

数据库服务器和业务服务器都连接成功后,开始对路由地址的数据进行处理

person.js文件如下:

let mongoose = require('mongoose')
// 结构对象
const personType = {name: {type: String,required: true},age: {type: Number,default: 18,},email: {type: String}
}
let personObj = new mongoose.Schema(personType)
let person = mongoose.model('accounts', personObj)
module.exports = person

3、进行数据库的操作:

此时的路由,不仅对存储的数据进行处理,还对前端的页面进行处理(页面和数据共用一个路由)

index.js文件如下:

var express = require('express');
var router = express.Router();
// 引入模型对象
const person = require('../model/person.js')/* GET home page. */
router.get('/', function(req, res, next) {res.render('index', { title: 'Express' });
});// 列表请求
router.get('/list', function(req, res, next) {person.find().then((data) => {res.render('list', {users: data});}).catch((err) => {res.end(err)})
});// 列表删除
router.get('/delete/:id', function(req, res, next) {person.deleteOne({_id: req.params.id}).then((data) => {res.redirect('/list')}).catch((err) => {res.end(err)})
})// 表单新增或者修改
router.get('/editForm', function(req, res, next) {if(req.query.id){person.find({_id: req.query.id}).then((data) => {res.render('editForm', {user: data[0]});}).catch((err) => {res.end(err)})} else {// 新增res.render('editForm', {user: {}});}
});// 表单提交
router.post('/editForm', function(req, res, next) {let editId = req.query.idif(editId) {person.updateOne({_id: editId}, {...req.body}).then((data) => {res.redirect('/list')}).catch((err) => {res.end(err)})} else {person.create({...req.body}).then((data) => {res.redirect('/editForm')}).catch((err) => {res.end(err)})}
});module.exports = router;

二、API接口:

1、定义:

一个接口,就是服务中的一个路由规则,用来操作数据。

2、作用:

进行前后端的通信,可以让前端处理前端页面,后端只处理数据即可。

3、基本组成:

① 请求方法

② 请求地址

③ 请求参数

④ 响应结果

4、免费接口:

① 网站:

https://free-api.com/

② 示例:

在这里插入图片描述

5、RESTful API

① 定义:

Web 服务接口的一种,是一种规范

② 编写接口注意:

(1)路径表示资源(数据库中的集合名称),不要有动词。

http://localhost:3000/list
http://localhost:3000/create ×

(2)操作和请求方法要对应
a、GET:获取资源
b、POST:创建资源
c、PUT:更新整个资源
d、PATCH:部分更新资源
e、DELETE:删除资源
(3)操作和状态码要对应

6、json-server

① 定义:

快速搭建 RESTful API 服务

② 安装:

npm i json-server -g

③ 使用:

(1)新建一个 db.json 文件,初始化本地数据库内容:
{"users": [{"id": 1,"name": "张三"},{"id": 2,"name": "李四"},{"id": 3,"name": "王五"}]
}
(2)以 db.json 文件所在的文件夹作为工作目录,执行启动服务的命令:

json-server --watch db.json

(3)查看数据库中的数据:

默认端口是3000,即访问users集合中的数据,需要访问 http://127.0.0.1:3000/users

7、接口测试工具:

apipost:推荐使用

https://www.apipost.cn/

postman:不推荐(保存接口必须登录,登录费劲)

https://www.postman.com/

8、项目练习(自用):实现前端路由与后端路由分离

将 第一部分的11、项目练习(自用):将本地数据库改为远程数据库 继续进行改造

① 新建一个 api 文件夹,用于进行后端路由(接口)的存储:

在该文件夹下新建 list.js 文件,用于编写与列表相关的后端接口

② 在 app.js中引入后端路由文件,并且使用该文件:

在这里插入图片描述

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
// 前端的页面路由
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
// 后端的服务api
var apiRouter = require('./routes/api/list')var app = express();// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));// 前端的页面路由
app.use('/', indexRouter);
app.use('/users', usersRouter);// 后端的服务api
app.use('/api', apiRouter)// catch 404 and forward to error handler
app.use(function(req, res, next) {next(createError(404));
});// error handler
app.use(function(err, req, res, next) {// set locals, only providing error in developmentres.locals.message = err.message;res.locals.error = req.app.get('env') === 'development' ? err : {};// render the error pageres.status(err.status || 500);res.render('error');
});module.exports = app;

③ 在 list.js 中编写后接口:

// 根据api进行后端数据的处理var express = require('express');
var router = express.Router();
// 引入模型对象
const person = require('../../model/person.js')// 获取所有列表
router.get('/list', function(req, res, next) {person.find().then((data) => {res.json({code: '0000',msg: '列表请求成功',data})}).catch((err) => {res.json({code: '1001',msg: '列表请求失败',data: err})})
});// 获取单条数据
router.get('/list/:id', function(req, res, next) {person.findById(req.params.id).then((data) => {res.json({code: '0000',msg: '数据请求成功',data})}).catch((err) => {res.json({code: '1002',msg: '数据请求失败',data: err})})
});// 列表新增
router.post('/list', function(req, res, next) {// 可以进行表单验证person.create({...req.body}).then((data) => {res.json({code: '0000',msg: '新增成功',data})}).catch((err) => {res.json({code: '1003',msg: '新增失败',data: err})})
});// 列表删除
router.delete('/list/:id', function(req, res, next) {person.deleteOne({_id: req.params.id}).then((data) => {res.json({code: '0000',msg: '删除成功',data})}).catch((err) => {res.json({code: '1004',msg: '删除失败',data: err})})
})// 列表修改
router.patch('/list/:id', function(req, res, next) {// 可以进行表单验证let editId = req.params.idperson.updateOne({_id: editId}, {...req.body}).then((data) => {res.json({code: '0000',msg: '修改成功',data})}).catch((err) => {res.json({code: '1005',msg: '修改失败',data: err})})
});module.exports = router;

④ 在 apipost 中进行调试:

在这里插入图片描述

三、会话控制:

1、会话控制介绍:

Express框架使用 中的 第三部分 -> 获取请求( / 设置响应)报文参数

2、练习项目添加身份的验证:

将 第二部分的8、项目练习(自用):实现前端路由与后端路由分离 继续进行改造
在这里插入图片描述

① 新建一个 auth 文件夹,用于保存用户相关的前端路由:

密码加密:https://www.npmjs.com/package/md5

新建注册路由页面sign.js

// 根据路由进行前端页面的显示,没有后端数据的处理var express = require('express');
var router = express.Router();
// 引入模型对象
const auth = require('../../model/auth.js')
// 做加密
var md5 = require('md5');// 注册页面显示 -- 因为有路由前缀,所以实际访问的是/a/sign
router.get('/sign', function(req, res, next) {res.render('auth/sign'); // 通过该路径去views文件夹找,找不到会报错
});// 注册页面显示 -- 因为有路由前缀,所以实际访问的是/a/login
router.get('/login', function(req, res, next) {res.render('auth/login'); // 通过该路径去views文件夹找,找不到会报错
});// 提交注册 -- 因为有路由前缀,所以实际访问的是/a/sign
router.post('/sign', function(req, res, next) {// 进行表单验证// 给密码进行加密let pwd = md5(req.body.pwd)auth.create({...req.body, pwd}).then((data) => {res.redirect('/a/login');  // 通过该路径去views文件夹找,找不到会报错}).catch((err) => {res.end(err)})
});module.exports = router;

② 新建一个 auth 文件夹,用于保存用户相关的前端页面:

新建用户注册页面文件auth.js

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1>注册</h1><form action="/a/sign" method="post"><div style="margin-bottom: 20px;"><label for="name">用户名:</label><input type="text" id="name" name="name" value=""></div><div style="margin-bottom: 20px;"><label for="pwd">密码:</label><input type="password" id="pwd" name="pwd" value=""></div><button type="submit">点击进行注册</button></form>
</body>
</html>

③ 新建用户模型文件auth.js,修改数据的结构类型和数据库的集合名称:

let mongoose = require('mongoose')
// 结构对象
const authType = {name: String,pwd: String
}
let authObj = new mongoose.Schema(authType)
let auth = mongoose.model('authors', authObj)
module.exports = auth

④ 在app.js中进行引入:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
// 前端的页面路由
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var authRouter = require('./routes/auth/sign');
// 后端的服务api
var apiRouter = require('./routes/api/list')var app = express();// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));// 前端的页面路由
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/a', authRouter);// 后端的服务api
app.use('/api', apiRouter)// catch 404 and forward to error handler
app.use(function(req, res, next) {next(createError(404));
});// error handler
app.use(function(err, req, res, next) {// set locals, only providing error in developmentres.locals.message = err.message;res.locals.error = req.app.get('env') === 'development' ? err : {};// render the error pageres.status(err.status || 500);res.render('error');
});module.exports = app;

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词