Mongoose 教程
约 1487 字大约 5 分钟
2025-03-15
一、介绍
Mongoose 是 MongoDB 的一个对象模型工具,是基于 node-mongodb-native 开发的 MongoDB nodejs 驱动,可以在异步的环境下执行。同时它也是针对 MongoDB 操作的一个对象模型库,封装了 MongoDB 对文档的的一些增删改查等常用方法,让 NodeJS 操作 Mongodb 数据库变得更加灵活简单。
Mongoose,因为封装了对 MongoDB 对文档操作的常用处理方法,可以高效的操作 mongodb,同时可以理解 mongoose 是一个简易版的 orm ,提供了类似 schema 定义,hook、plugin、virtual、populate 等机制,让 NodeJS 操作 Mongodb 数据库变得特别简单!
二、快速认识
Schema
相当于 collection
的 validator
,是集合的结构定义
Model
相当于collection
阅读以下示例代码:
// 引入依赖
const mongoose = require("mongoose");
// 连接数据库
mongoose.connect("mongodb://ip:port/test");
// 创建模型(集合)
const Cat = mongoose.model("Cat", { name: String });
// 新增一个对象
const kitty = new Cat({ name: "kangkang" });
kitty.save().then(() => console.log("meow"));
三、连接数据库
1、单个默认连接 connect()
//1. 安装 mongoose
//2. 导入 mongoose
const mongoose = require("mongoose");
//3. 连接数据库
mongoose.connect("mongodb://127.0.0.1:27017/bilibili");
//4. 设置连接回调
//连接成功
mongoose.connection.on("open", () => {
// CURD 逻辑
consol.log("链接成功~~");
});
mongoose.connection.once("open", () => {
consol.log("只有第一次链接成功时,打印此消息~~");
});
//连接出错
mongoose.connection.on("error", () => {
console.log("连接出错~~");
});
//连接关闭
mongoose.connection.on("close", () => {
console.log("连接关闭");
});
on 和 once 的区别
- on 方法 : 每次数据库成功链接时,回调函数都会被调用。这意味着如果数据库多次成功连接,回调函数会多次执行。你可以用它来处理连接错误、记录日志等。
- once 方法 : 每次数据库成功链接时,回调函数只会在事件第一次发生时执行一次。当数据库第一次成功连接时,这个回调函数会被执行一次,之后即使事件再次发生,回调函数也不会再次执行 。适合做一些初始化操作
2、多个连接(连接池) createConnection()
const conn = mongoose.createConnection("mongodb://127.0.0.1:27017/bilibili");
四、模式(Schema)和模型(Model)
1、定义模式
const UserSchema = new mongoose.Schema({
name: String,
});
2、创建模型
给user 模型
绑定 UserSchema 模式
const User = mongoose.model("User", UserSchema);
五、字段类型和验证
1、字段类型
类型 | 描述 |
---|---|
String | 字符串 |
Number | 数字 |
Boolean | 布尔值 |
Array | 数组,也可以使用 [] 来标识 |
Date | 日期 |
Buffer | 对象 |
Mixed | 任意类型,需要使用 mongoose.Schema.Types.Mixed 指定 |
ObjectId | 对象 ID,需要使用 mongoose.Schema.Types.ObjectId 指定 |
Decimal 128 | 高精度数字,需要使用 mongoose.Schema.Types.Decimal128 指定 |
2、内置验证
Mongoose 有一些内置验证器。
- 所有
SchemaTypes
都有内建required
验证器。required
验证器使用checkRequired()
函数 判定这个值是否满足required
验证器 Numbers
有min
和max
验证器.Strings
有enum
、match
、maxlength
和minlength
验证器
例如:
//5. 创建文档结构对象
let BookSchema = new mongoose.Schema({
title: {
type: String,
required: true, // 必填项
default: "匿名", // 默认值
enum: ["男", "女"], // 枚举值,设置的值必须是数组中的
unique: true, // 需要新建的或者重建的集合才能生效
},
author: {
type: String,
required: [true, "不能为空"], // 必填项
},
price: {
type: Numbers,
min: [6, "min val is 6"],
max: 12,
},
});
3、自定义验证
如果内建检验器不够用了,你可以定义满足自己需要的检验器
自定义检验器通过传入一个检验函数来定义
var userSchema = new Schema({
phone: {
type: String,
validate: {
validator: function (v) {
return /\d{3}-\d{3}-\d{4}/.test(v);
},
message: "{VALUE} is not a valid phone number!",
},
required: [true, "User phone number required"],
},
});
六、CURD 操作
1、新增数据
1、新建 Schema save()
// 构建文档
const user = new User({ name: "jty" });
console.log(user.name);
await user.save(); // 保存进数据库
2、其他方式
await User.create({ name: "jty" });
await User.insertMany([{ name: "jty" }]);
await User.insertOne({ name: "jty" });
2、删除数据
一般建议根据主键来删除数据,删除多条数据的时候可以使用非主键
await User.remove({ name: "jtt" });
await User.deleteOne({ name: "jtt" });
await User.deleteMany({ name: "jtt" });
3、更新数据
一般建议根据主键来更新数据,更新多条数据的时候可以使用非主键
await Tank.update({ name: "jty" }, { name: "jtt" });
await Tank.updateOne({ name: "jty" }, { name: "jtt" });
await Tank.updateMany({ name: "jty" }, { name: "jtt" });
await Tank.replaceOne({ name: "jty" }, { name: "jtt" });
4、查询数据
Tank.find({ size: "small" });
Tank.findById("5dd662b5381fc316b44ce167");
Tank.findOne({ size: "small" });
其他一些特殊的查询方法
Model.findOneAndUpdate();
Model.findByIdAndUpdate();
Model.findOneAndRemove();
Model.findByIdAndRemove();
5、条件控制
1、lt/gt/lte/gte/$ne
分别代表 <
, >
, <=
, >=
, !==
Book.find({ price: { $lt: 20 } });
2、$or
// 查询曹雪芹或者余华书
Book.find({ $or: [{ autor: "曹雪芹" }, { autor: "余华" }] });
2、$and
// 查询价格大于20,小于70的书
Book.find({ $and: [{ price: { $gt: 20 } }, { price: { $lt: 70 } }] });
3、正则匹配
条件中可以直接使用 JS 的正则语法,通过正则可以进行模糊查询
db.students.find({ name: /imissyou/ });
七、查询器
Query
构造函数,用来构建查询器(query),不过并不需要直接实例化 Query
对象,而是用 Model 的 Model.find()
这些函数。
1、select() 字段筛选
指定查询包含或者排除的字段。推荐使用对象标记法
// 选择 a 和 b 字段,排除其他的
query.select("a b");
// 排除 c 和 d 字段,选择其他的
query.select("-c -d");
// 如果存在已经有"-"前缀的字段,可以用对象标记法 推荐使用
query.select({ a: 1, b: 1 });
query.select({ c: 0, d: 0 });
// 强制包含已经在 schema level 排除的字段
query.select("+path");
2、sort() 排序
如果传入的参数是个对象,字段值可以是 asc
, desc
, ascending
, descending
, 1
和 -1
。
query.sort({ a: 1, b: 1 });
query.sort({ c: 0, d: 0 });
3、limit() 截断
截取固定条数
query.limit(10);
4、skip() 跳过
跳过固定条数
query.skip(10);
5、exec() 执行
执行当前 query 条件
query.exec();
6、where()
创建并应用一个查询
User.find({ age: { $gte: 21, $lte: 65 } }, callback);
// 上下等价
User.where("age").gte(21).lte(65).exec(callback);
链式使用,可以查询多个条件
User.where("age").gte(21).lte(65).where("name", /^b/i);
更新日志
e7112
-1于