快速上手mongoose
前言
Mongoose 是 MongoDB 的一个对象模型工具,是基于 node-mongodb-native 开发的 MongoDB nodejs 驱动,可以在异步的环境下执行。同时它也是针对 MongoDB 操作的一个对象模型库,封装了MongoDB 对文档的的一些增删改查等常用方法,让 NodeJS 操作 Mongodb 数据库变得更加灵活简单。
记录使用MongoDB非关系型数据库时,使用Express+Mongoose的操作。
项目依赖
初始化项目之后复制如下到package.json安装即可1
2
3
4
5
6"dependencies": {
"body-parser": "^1.20.0",
"cors": "^2.8.5",
"express": "^4.18.1",
"mongoose": "^6.3.4"
}
express模板
由于只是演示操作,下列全部都写在了app.js中,具体使用按业务场景划分文件模块1
2
3
4
5
6
7
8
9const bodyParser = require('body-parser'); // 引入body-parser模块
const express = require('express'); // 引入express模块
const cors = require('cors'); // 引入cors模块
const app = express();
app.use(bodyParser.json()); // 解析json数据格式
app.use(bodyParser.urlencoded({
extended: true
})); // 解析form表单提交的数据application/x-www-form-urlencoded
app.use(cors()); // 注入cors模块解决跨域
mongoose模板
分为几部分:
- 引入mongoose
- 定义连接的数据库
- 连接数据库
代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//引入mongoose
const mongoose = require('mongoose');
//定义字符串常量
const db_url = "mongodb://localhost:27017/miniprogram"
//1.连接数据库
mongoose.connect(db_url, {
useNewUrlParser: true,
useUnifiedTopology: true
})
//2.连接成功
mongoose.connection.on('connected', function () {
console.log('连接成功:', db_url);
})
//3.连接失败
mongoose.connection.on('error', function (err) {
console.log('连接错误:', err);
})
//4.断开连接
mongoose.connection.on('disconnection', function () {
console.log('断开连接');
})
新建schema
mongoose是封装过后的mongodb指令,它需要我们先新建一个schema,内部是所需的字段名称和类型。
下面是schema的介绍
Schema是一种以文件形式存储的数据库模型骨架,无法直接通往数据库端,也就是说它不具备对数据库的操作能力,仅仅只是定义数据库模型在程序片段中的一种表现,可以说是数据属性模型(传统意义的表结构),又或着是“集合”的模型骨架。
代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const commoditiesSchema = new Schema({
_id: {
type: String
},
goods: {
type: Object
},
typeID: {
type: String
},
typeImage: {
type: String
},
typeTitle: {
type: String
},
});
创建模型
模型的定义
模型(Model)是由Schema构造生成的模型,除了Schema定义的数据库骨架以外,还具有数据库操作的行为,类似于管理数据库属性、行为的类
第二步需要创建模型,如果数据库中没有这张表(复数名称),则新建一张。
创建表名的规则是:传入的单词的复数,如果已经是复数,则使用复数
egfood
-> foods
code1
2// 引号内传入的是表名 自动转为复数
const commodities = mongoose.model('commodities', commoditiesSchema);
schema和model最好不要在接口里面写
原因1: 请求多次会由于利用了重复的模型报错(模型不允许overwrite)
原因2: 全局可复用
查询find
mongoose中提供了几种查询方法,find
、findById
、findOne
。都是模型的api,所以一定要新建模型
findById
返回的结果是数组
需要传入两个参数,一个是对象包裹的id,可以是_id
,第二个是一个回调函数,其中有两个参数err
和data
,返回查询的结果或者异常情况。1
2
3
4
5
6
7
8
9
10
11
12
13commodities.findById({
_id
}, (err, data) => {
if (err) {
console.log(err)
} else {
// 一般返回三个值 code msg 和 result
res.json({
code: 1,
result: data
})
}
})
find
返回的结果是数组
两种情况
第一种只传一个回调函数,则返回对应模型的全部字段值
第二种:
需要传入三个参数,第一个是对象包裹的查询条件,第二个是对象包裹的返回结果(用于筛选),key是模型的字段,value是1或者0,如果是1则返回该结果,如果是0则不返回,第三个是回调函数1
2
3
4
5
6
7
8
9
10
11commodities.find({
_id,
},{goods:1},(err, data) => {
if (err) {
console.log('查找异常', err);
} else {
console.log('data',data)
res.json({
result:data
})
}
findOne
返回单个结果,是一个数据对象。也是可以传入三个参数,依据是否大量查询使用不同的指令对性能的影响可能不一样
新增(创建实体)
实体的定义如下
实体(Entity)是由Model创建的实体,使用save方法保存数据,Model和Entity都有能影响数据库的操作,但Model比Entity更具操作性。
新增需要建立实体,实体是根据模型建立的。实体中有save方法,可以让我们对数据库进行插入操作,也是传递一个回调参数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// 获取query参数
let {
addr,
name,
phone,
time
} = req.query;
//创建实体
let AddEntity = new address({
addr,
name,
phone,
time
})
AddEntity.save((err, data) => {
if (err) {
console.log('插入失败:', err);
} else {
res.json({
code: 0,
msg: '插入成功',
})
}
})
删除delete
删除的操作是基于模型的,是模型中的方法
删除有两个方法,一个是deleteOne
和remove
deleteOne
传递两个参数,一个是查找条件,一个是回调函数
代码1
2
3
4
5
6
7
8
9
10
11
12
13address.deleteOne({
_id
}, (err, data) => {
if (err) {
console.log('删除失败:', err);
} else {
res.json({
code: 0,
msg: '删除成功',
})
}
})
更新update
更新的操作是基于模型的,是模型的api
updateOne
方法,传入三个参数
- 对象包裹的查询条件
- 对象包裹的更新数据
- 回调参数
代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18address.updateOne({
_id
}, {
addr,
name,
phone,
time
}, (err, data) => {
if (err) {
console.log('修改失败:', err);
} else {
res.json({
code: 0,
msg: '修改成功',
})
}
})
另外还有findByIdAndUpdate
,findOneAndUpdate
方法
总结
在mongoose操作中需要注意如果数据库中没有该表,会新建为复数名称的表,所以导入数据的时候应该在库建立好之后再考虑导入
如果已经有表,对应的规则在schema中也不能出错,否则返回错误类型的约束