一、简介
- 基于 node-mongodb-native MongoDB nodejs 驱动,可以在异步的环境下执行。
- 它是针对 MongoDB 操作的一个对象文档型数据库,封装了MongoDB 对文档的的一些增删改查等常用方法
- 从6.0.0版开始,Mongoose中的方法不再接受回调作为最后一个参数,而是返回一个promise
1.1 准备工作
- 安装mongoose,当前最新版本为 7.0.4
npm i mongoose
- 引用mongoose
const mongoose = require('mongoose');
- 连接mongodb服务 ,默认端口是
27017
//连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/test1');
1.2 连接数据库
const mongoose = require('mongoose');
mongoose.set('strictQuery',true);
//连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/test1');
//设置回调
//连接成功的回调
// mongoose.connection.on('open',()=>{
// console.log('sucess')
// });
//事件回调函数只执行一次
mongoose.connection.once('open',()=>{
console.log('sucess')
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('error')
});
//设置连接关闭
mongoose.connection.on('close',()=>{
console.log('close')
});
//延迟关闭
setTimeout(() => {
mongoose.disconnect();
}, 2000);
二、CRUD(增删改查)
- Mongoose 里,一切都始于Schema。Schema的功能不只是定义文档结构和属性类型。它可以定义——
- document 的 instance methods
- model 的 static Model methods
- 复合索引
- 文档的生命周期钩子,也成为中间件
- 每个 schema 都会映射到一个 MongoDB collection ,并定义这个collection里的文档的构成。
- 文档 里每个属性的类型都会被转换为在 创建文档的结构对象时 定义对应的 SchemaTypes(模式类型)。
- 允许使用的 SchemaTypes 有:
类型 | 描述 |
---|---|
String | 字符串 |
Number | 数字 |
Date | 日期 |
Buffer | Buffer对象 |
Boolean | 布尔值 |
Mixed | 任意类型,需要使用 mongoose.Schema.Types.Mixed 指定 |
ObjectId | 对象ID,需要使用 mongoose.Schema.Types.ObjectId 指定, 主要用于外键,适合联合查询 |
Array | 数组,也可使用 [ ] 来标识 |
Decimal128 | 高精度数字,需要使用 mongoose.Schema.Types.Decimal128 指定 |
2.1 插入文档
const mongoose = require('mongoose');
mongoose.set('strictQuery', true);
//连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/test1');
//设置回调
//连接成功的回调
// mongoose.connection.on('open',()=>{
// console.log('sucess')
// });
//事件回调函数只执行一次
mongoose.connection.once('open', () => {
//1.创建文档的结构对象 设置集合中文档的属性以及属性值的类型
let blogSchema = new mongoose.Schema({
title: String,
author: String,
price: String,
is_hot: Boolean,
tags:[],
pub_time:Date,
test:mongoose.Schema.Types.Mixed,
});
//2.创建模型对象 对文档操作的封装对象
let BlogModel = mongoose.model('Blog', blogSchema);
//3.新增
BlogModel.create({
title: '西游记',
author: '吴承恩',
price: 34,
is_hot: true,
tags:['鬼怪','人性'],
pub_time:new Date(),
test:26
}).then((res) => {
console.log(res)
//4.关闭数据连接 项目运行过程中不会添加该代码
mongoose.disconnect();
}).catch((err) => {
console.log(err)
})
//console.log('sucess')
});
//设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('error')
});
//设置连接关闭
mongoose.connection.on('close', () => {
console.log('close')
});
> use test1
switched to db test1
> show collections
account
blogs
book
user> db.blogs.find()
{ "_id" : ObjectId("6445353d87dd3243c3a24cd8"), "title" : "西游记", "author" : "吴承恩", "price" : "34", "is_hot" : true, "tags" : [ "鬼怪", "人性" ], "pub_time" : ISODate("2023-04-23T13:40:13.909Z"), "test" : 26, "__v" : 0 }
2.1.1 字段值验证
Mongoose有一些内置验证器,可以对字段进行验证
-
必填项 (required: true)
-
默认值 (default: '匿名')
-
枚举值 (enum: ['言情', '志怪', '玄幻'])
-
唯一值 (unique: true)
const mongoose = require('mongoose');
mongoose.set('strictQuery', true);
//连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/test1');
mongoose.connection.once('open', () => {
//1.创建文档的结构对象 设置集合中文档的属性以及属性值的类型
let BookSchema = new mongoose.Schema({
title: {
type: String,
//表明该属性必填
required: true,
//设置为唯一值,想看到效果必须重建集合
unique: true
},
author: {
type: String,
//默认值
default: '匿名'
},
price: Number,
style: {
type: String,
//枚举值
enum: ['言情', '志怪', '玄幻']
}
});
//2.创建模型对象 对文档操作的封装对象
let BookModel = mongoose.model('books', BookSchema);
//3.新增
BookModel.create({
//Path `title` is required.
//MongoServerError: E11000 duplicate key error collection: test1.books index: title_1 dup key: { title: "xxx" }
title: 'xxx',
price: 30,
// `xx` is not a valid enum value for path `style`.
style: '志怪'
}).then((res) => {
console.log(res)
//4.关闭数据连接 项目运行过程中不会添加该代码
mongoose.disconnect();
}).catch((err) => {
console.log(err)
})
//console.log('sucess')
});
//设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('error')
});
//设置连接关闭
mongoose.connection.on('close', () => {
console.log('close')
});
2.2 删除文档
-
删除一条 deleteOne(条件)
-
批量删除 deleteMany(条件)
const mongoose = require('mongoose');
mongoose.set('strictQuery', true);
//连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/test1');
mongoose.connection.once('open', () => {
//1.创建文档的结构对象 设置集合中文档的属性以及属性值的类型
let MovieSchema = new mongoose.Schema({
title: {
type: String,
//表明该属性必填
required: true,
//设置为唯一值,想看到效果必须重建集合
unique: true
},
author: {
type: String,
//默认值
default: '匿名'
},
price: Number,
style: {
type: String,
//枚举值
enum: ['言情', '志怪', '玄幻']
}
});
//2.创建模型对象 对文档操作的封装对象
//mongoose 会使用集合名称的复数创建集合 movie==>movies
let MovieModel = mongoose.model('movie', MovieSchema);
//3.删除一条
// MovieModel.deleteOne({_id:'64453dc8503e3b434d863272'})
// .then((res) => {
// console.log(res);
// console.log('删除成功!')
// mongoose.disconnect();
// }).catch((err) => {
// console.log(err)
// })
//4.删除多条
MovieModel.deleteMany({style:'玄幻'})
.then((res) => {
console.log(res);
console.log('删除成功!')
mongoose.disconnect();
}).catch((err) => {
console.log(err)
})
});
//设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('error')
});
//设置连接关闭
mongoose.connection.on('close', () => {
console.log('close')
});
2.3 更新文档
-
更新一条 updateOne(条件)
-
批量更新 updateMany(条件)
const mongoose = require('mongoose');
mongoose.set('strictQuery', true);
//连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/test1');
mongoose.connection.once('open', () => {
//1.创建文档的结构对象 设置集合中文档的属性以及属性值的类型
let BookSchema = new mongoose.Schema({
title: {
type: String,
//表明该属性必填
required: true,
//设置为唯一值,想看到效果必须重建集合
unique: true
},
author: {
type: String,
//默认值
default: '匿名'
},
price: Number,
style: {
type: String,
//枚举值
enum: ['言情', '志怪', '玄幻']
}
});
//2.创建模型对象 对文档操作的封装对象
//mongoose 会使用集合名称的复数创建集合 movie==>movies
let BookModel = mongoose.model('movie', BookSchema);
//3.更新一条
// BookModel.updateOne({ title:"河西"},{price:9.9}).then((res) => {
// console.log(res)
// console.log('更新成功')
// mongoose.disconnect();
// }).catch((err) => {
// //console.log(err)
// console.log('更新失败')
// })
//4.批量更新
BookModel.updateMany({ author:"匿名"},{price:25}).then((res) => {
console.log(res)
console.log('更新成功')
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('更新失败')
})
});
//设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('error')
});
//设置连接关闭
mongoose.connection.on('close', () => {
console.log('close')
});
2.4 读取文档
-
读取一条 findOne(条件)
-
根据id获取 findById(id)
-
批量更新 updateMany(条件)
const mongoose = require('mongoose');
mongoose.set('strictQuery', true);
//连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/test1');
mongoose.connection.once('open', () => {
//1.创建文档的结构对象 设置集合中文档的属性以及属性值的类型
let BookSchema = new mongoose.Schema({
title: {
type: String,
//表明该属性必填
required: true,
//设置为唯一值,想看到效果必须重建集合
unique: true
},
author: {
type: String,
//默认值
default: '匿名'
},
price: Number,
style: {
type: String,
//枚举值
enum: ['言情', '志怪', '玄幻']
}
});
//2.创建模型对象 对文档操作的封装对象
//mongoose 会使用集合名称的复数创建集合 movie==>movies
let BookModel = mongoose.model('movie', BookSchema);
//3. 读取单条
// BookModel.findOne({
// title: "河西"
// }).then((res) => {
// console.log(res)
// mongoose.disconnect();
// }).catch((err) => {
// //console.log(err)
// console.log('获取失败')
// })
// 根据id获取
// BookModel.findById('64453f7442d5be31a5733ce4').then((res) => {
// console.log(res)
// mongoose.disconnect();
// }).catch((err) => {
// //console.log(err)
// console.log('获取失败')
// })
//4.批量获取
BookModel.find({
price: 25
}).then((res) => {
console.log(res)
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('获取失败')
})
});
//设置连接错误的回调
mongoose.connection.on('error', () => {
console.log('error')
});
//设置连接关闭
mongoose.connection.on('close', () => {
console.log('close')
});
三、条件控制
3.1 运算符
在mongodb不能用 > < >= <= !== 等运算符,需要使用替代符
-
> 使用 $gt
-
< 使用 $lt
-
>= 使用 $gte
-
<= 使用 $lte
-
!== 使用 $ne
//价格小于30
BookModel.find({
price: {
$lt: 30
}
}).then((res) => {
console.log(res)
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('获取失败')
})
3.2 逻辑运算
-
$or 逻辑或
-
$and 逻辑与
//价格小于30
BookModel.find({
price: {
$lt: 30
}
}).then((res) => {
console.log(res)
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('获取失败')
})
//逻辑或
BookModel.find({
$or: [{price: 68},{price: 48}]
}).then((res) => {
console.log(res)
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('获取失败')
})
//逻辑与 大于在前,小于在后
BookModel.find({
$and: [{
price: {
$gt: 20
}
}, {
price: {
$lt: 50
}
}]
}).then((res) => {
console.log(res)
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('获取失败')
})
3.3 正则匹配
条件中可以直接使用JS正则语法,通过正则可以实现模糊查询
//正则表达式
BookModel.find({
//检测title中带有‘西’
title: /西/
}).then((res) => {
console.log(res)
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('获取失败')
})
BookModel.find({
//检测title中带有‘2’
title: new RegExp('2')
}).then((res) => {
console.log(res)
mongoose.disconnect();
}).catch((err) => {
//console.log(err)
console.log('获取失败')
})
四、个性化读取
-
字段筛选 select
-
数据排序 sort(1/-1) 1正序,-1倒序
-
数据截取 skip(跳过) limit(限定)
//字段筛选 select title,style
//数据排序 sort 升序是1,倒序是-1
//数据截断 limit
BookModel.find().select({
title: 1,
style: 1
})
.sort({
price: 1,
})
//跳过1,2,取3,4
.skip(2)
.limit(2)
.then((res) => {
console.log(res)
}).catch((err) => {
console.log(err)
console.log('查询失败')
})
五、mongoose模块化
-
config.js(配置文件)
- 后续需要更改的信息,如数据库地址,端口,数据库名等
//配置文件
module.exports = {
HOST: '127.0.0.1',
PORT: 27017,
NAME: 'test1'
}
-
db.js(配置数据库连接)
module.exports = function (success,error) {
//判断 error 为其设置一个默认值
if(typeof error !== 'function'){
(error) => {
console.log('连接失败');
}
}
//导入mongoose
const mongoose = require('mongoose');
//导入配置文件
const {HOST,PORT,NAME} = require('../config/config')
mongoose.set('strictQuery', true);
//连接mongodb服务 数据库名称
mongoose.connect(`mongodb://${HOST}:${PORT}/${NAME}`);
mongoose.connection.once('open', () => {
success();
});
//设置连接错误的回调
mongoose.connection.on('error', () => {
error();
});
//设置连接关闭
mongoose.connection.on('close', () => {
console.log('close')
});
}
-
BlogModel.js(模型对象)
- 创建文档的结构对象,封装文档,创建模型对象,用于后续文档操作
const mongoose = require('mongoose');
//1.创建文档的结构对象 设置集合中文档的属性以及属性值的类型
let blogSchema = new mongoose.Schema({
title: String,
author: String,
price: String,
is_hot: Boolean,
tags: [],
pub_time: Date,
test: mongoose.Schema.Types.Mixed,
});
// //2.创建模型对象 对文档操作的封装对象
let BlogModel = mongoose.model('Blog', blogSchema);
//暴露模型对象
module.exports = BlogModel;
-
index.js(主文件)
//导入db 函数
const db = require('./db/db')
const mongoose = require('mongoose');
//导入模型对象
const BlogModel = require('./module/BlogModel')
db((data) => {
// //3.新增
BlogModel.create({
title: '路西',
author: '呵呵呵',
price: 34,
is_hot: true,
tags: ['鬼怪', '人性'],
pub_time: new Date(),
test: 26
}).then((res) => {
console.log(res)
//4.关闭数据连接 项目运行过程中不会添加该代码
mongoose.disconnect();
}).catch((err) => {
console.log(err)
})
console.log('success')
});