操作 MongoDB
MongoDB
MongoDB 是一个基于分布式文件存储的数据库
相比较纯文件管理数据有如下特点特点
- 速度快
- 扩展性强
- 安全性强
三个核心概念:
- 数据库(database):数据库是一个数据仓库,可以创建很多数据库
- 集合(collection):集合位于数据库之中,在集合中可以存放很多文件
- 文档(document):文档是数据库中的最小单位,类似于 js 中的对象
使用 Mongoose
- mongoose 是一个可以通过 node 来操作 mongodb 的包
- mongoose 是一个对象文档模型库,对 node 原生的 mongodb 进行了封装,提供了更多功能。
- mongoose 中的对象:
- Schema 模式对象,约束了数据库中的文档结构
- Model 模型对象,作为集合中的所有文档表示,相当于 mongodb 数据库中的结合 collection
- Document 文档对象,表示集合中的具体文档,相当于集合中的一个具体文档
mongoose的好处
- 可以为文档创建一个模式结构
- 可以对模型中的对象/文档进行验证
- 数据可以通过类型转换转换为对象模型
- 可以使用中间件来应用业务逻辑挂钩
- 比Node原生的MongoDB驱动更容易
连接数据库
// config/db.config.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://127.0.0.1:27017/stu')
mongoose.connection.once('open',() => {
console.log('连接成功')
})
mongoose.connection.on('error',() => {
console.log('连接错误')
})
mongoose.connection.on('close',() => {
console.log('连接断开')
})
// 断开数据库连接
mongoose.disconnect()
在 bin 目录下的 www 文件中直接使用 require('../config/cdb.config.js') 进行数据库的连接启动
创建模式对象和模型对象
数据库中的 Schema 是数据库的对象的集合,可以简单理解为表;每个 schema 会映射到 mongodb 中的 collection。
字段类型
类型 | 作用 |
---|---|
String | 定义字符串 |
Number | 定义数字 |
Date | 定义日期 |
Buffer | 定义二进制 |
Boolean | 定义布尔值 |
Mixed | 定义混合类型 |
ObjectId | 定义对象ID |
Array | 定义数组 |
// model/BookModels
const mongoose = require('mongoose')
const BookSchema = mongoose.Schema({
name: { type: String, require: true }, // 名称 unique: true必须唯一 不可以重复 不可以为空
author: { type: String, default: '匿名' }, // 作者 默认值
price: { type: Number, require: true },
_isHot: { type: Boolean, enum: [true, false] },
tags: Array,
data: { type: Date, require: true }
})
// 第一个参数表示创建的集合的名称,第二个参数表示利用的模式对象(第三个参数是强行指定集合名称)
const BookModles = mongoose.models('books',BookSchema)
module.export = BookModles
注意:
mongoose 支持 es6,在我自己操作时,如果使用了回调函数形式的方法来进行数据库操作,会报错,以 save()为例:
MongooseError: Model.prototype.save() no longer accepts a callback
所以我下面使用的是 es6 的方式进行 mongoose 的使用
新增文档(三种)
save()
- 操作文档
const mongoose = require('mongoose')
const BookModel = require('../model/BookModel')
// 链式调用
BookModel({
name: '西游记7',
author: '吴承恩',
price: 72.75,
_isHot: true,
tags: ['社会', '恐怖', '晚上不要看'],
data: new Date()
}).save().then(data => {
console.log(data)
}).catch(err=>{
console.log(err)
})
create()
- 操作模型
BookModel.create({
name: '西游记2',
author: '吴承恩',
price: 72.75,
_isHot: true,
tags: ['社会', '恐怖', '晚上不要看'],
data: new Date()
}).then(data => {
console.log(data)
})
insertMany()
BookModel.insertMany(
[{
name: '西游记12',
author: '吴承恩',
price: 72.75,
_isHot: true,
tags: ['社会', '恐怖', '晚上不要看'],
data: new Date()
},
{
name: '西游记13',
author: '吴承恩',
price: 72.75,
_isHot: true,
tags: ['社会', '恐怖', '晚上不要看'],
data: new Date()
}]
).then(data=>console.log('data',data))
文档查询
_id | name | price | ···· | __ v |
---|---|---|---|---|
645af6a79964b2ec38f406a9 | 西游记 | 19.9 | ···· | 0 |
645af6a79964b2ec38f406aa | 红楼梦 | 29.9 | ···· | 0 |
645af6a79964b2ec38f406ab | 三国演义 | 25.9 | ···· | 0 |
645af6a79964b2ec38f406ac | 水浒传 | 20.9 | ···· | 0 |
find()
BookModel.find({price: 25.9}).then(data=>console.log(data));
findById()
BookModel.findById('645af6a79964b2ec38f406aa').then(data=>console.log(data));
findOne()
- 返回查询到的数据的第一个
BookModel.findOne({name: '西游记'}).then(data => {console.log(data)});
条件查询 $where
BookModel.find({$where : "/^西游记/.test(this.name)"}).then(data=>console.log(data)).catch(err=>console.log(err))
其他常用查询条件
BookModel.find({ price: { $lt: 20 } }, { id: 0 }).then(data => { console.log(data) });
BookModel.find({ $or: [{ price: { $lt: 20 } }, { price: { $gt: 70 } }] }).then(data => { console.log(data) });
BookModel.find({ $and: [{ price: { $gt: 20 } }, { price: { $lt: 70 } }] }).then(data => { console.log(data) });
BookModel.find({name:/^西/}).then(data=>console.log(data));
BookModel.find({name:new RegExp('西')}).then(data=>console.log(data));
特定类型查询
BookModel.find({ $and: [{ price: { $gt: 20 } }, { price: { $lt: 70 } }] })
.select({ author: 1, price: 1, _id: 0 }) // 1为要显示的值,0为不显示的值
.then((data) => console.log(data))
.catch((err) => console.error(err));
BookModel.find({ $and: [{ price: { $gt: 20 } }, { price: { $lt: 70 } }] })
.select({ author: 1, price: 1, _id: 0 })
.sort({ price: 1 }) // 1 升序,-1 降序
.then((data) => console.log(data))
.catch((err) => console.error(err));
BookModel.find({ $and: [{ price: { $gt: 20 } }, { price: { $lt: 70 } }] })
.select({ author: 1, price: 1, _id: 0 })
.sort({ price: 1 }) // 1 升序,-1 降序
.skip(2) // 跳过两个
.limit(5) // 截取五个
.then((data) => console.log(data))
.catch((err) => console.error(err));
文档更新
updateOne
- 只更新符合条件的第一条
BookModel.updateOne({name:'西游记'},{price: 7.5}).then(data=>{console.log(data)});
updateMany
- 更新符合条件的每一条
BookModel.updateMany({_isHot: true},{price: 100}).then(data=>{console.log(data)});
文档删除
deleteOne
- 删除符合条件的第一条
BookModel.deleteOne({_id:'645af6a79964b2ec38f406a9'}).then(data=>{
console.log(data);
});
deleteMany
- 删除符合条件的每一条
BookModel.deleteMany({_isHot:true}).then(data=>{
console.log(data);
});
findOneAndRemove()
- 找到并删除符合条件的第一条
BookModel.findOneAndRemove({_isHot: true}).then(data=>{console.log(data)})
前后钩子
- 前后钩子 pre 和 post 方法,是中间件
- 在 schema 上指定
- 在执行一些操作时设置前后钩子
- pre():在执行操作前执行,需要使用 next() 继续下一步操作
- pre():在执行操作后执行,不可以使用 next()
// 这些钩子需要在 Schema 的实例对象上挂载
let BookSchema = mongoose.Schema({
// 省略
})
BookSchema.pre('find',(next)=>{
console.log('pre被执行')
next()
})
BookSchema.post('find',(data)=>{
console.log('post被执行',data)
})