前言

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
9
const 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模板

分为几部分:

  1. 引入mongoose
  2. 定义连接的数据库
  3. 连接数据库

代码

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
17
const commoditiesSchema = new Schema({
_id: {
type: String
},
goods: {
type: Object
},
typeID: {
type: String
},
typeImage: {
type: String
},
typeTitle: {
type: String
},
});

创建模型

模型的定义

模型(Model)是由Schema构造生成的模型,除了Schema定义的数据库骨架以外,还具有数据库操作的行为,类似于管理数据库属性、行为的类


第二步需要创建模型,如果数据库中没有这张表(复数名称),则新建一张。

创建表名的规则是:传入的单词的复数,如果已经是复数,则使用复数

eg
food -> foods

code

1
2
// 引号内传入的是表名 自动转为复数
const commodities = mongoose.model('commodities', commoditiesSchema);

schema和model最好不要在接口里面写
原因1: 请求多次会由于利用了重复的模型报错(模型不允许overwrite)
原因2: 全局可复用

查询find

mongoose中提供了几种查询方法,findfindByIdfindOne。都是模型的api,所以一定要新建模型

findById 返回的结果是数组
需要传入两个参数,一个是对象包裹的id,可以是_id,第二个是一个回调函数,其中有两个参数errdata,返回查询的结果或者异常情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
commodities.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
11
commodities.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

删除的操作是基于模型的,是模型中的方法
删除有两个方法,一个是deleteOneremove

deleteOne传递两个参数,一个是查找条件,一个是回调函数

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
address.deleteOne({
_id
}, (err, data) => {
if (err) {
console.log('删除失败:', err);
} else {
res.json({
code: 0,
msg: '删除成功',
})

}
})

更新update

更新的操作是基于模型的,是模型的api

updateOne方法,传入三个参数

  1. 对象包裹的查询条件
  2. 对象包裹的更新数据
  3. 回调参数

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
address.updateOne({
_id
}, {
addr,
name,
phone,
time
}, (err, data) => {
if (err) {
console.log('修改失败:', err);
} else {
res.json({
code: 0,
msg: '修改成功',
})

}
})

另外还有findByIdAndUpdate,findOneAndUpdate方法

总结

在mongoose操作中需要注意如果数据库中没有该表,会新建为复数名称的表,所以导入数据的时候应该在库建立好之后再考虑导入

如果已经有表,对应的规则在schema中也不能出错,否则返回错误类型的约束