阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Mongoose的核心特性

Mongoose的核心特性

作者:陈川 阅读数:16963人阅读 分类: MongoDB

Mongoose是一个优秀的Node.js对象模型工具,专为MongoDB设计。它提供了强大的数据建模、验证、查询构建和中间件支持,简化了与MongoDB的交互过程。

数据建模与模式定义

Mongoose的核心是Schema(模式),它定义了文档的结构、字段类型和验证规则。通过Schema可以精确控制数据的形状和行为。例如:

const mongoose = require('mongoose');
const { Schema } = mongoose;

const userSchema = new Schema({
  username: {
    type: String,
    required: true,
    unique: true,
    minlength: 3,
    maxlength: 20
  },
  email: {
    type: String,
    required: true,
    match: /.+\@.+\..+/
  },
  age: {
    type: Number,
    min: 18,
    max: 120
  },
  createdAt: {
    type: Date,
    default: Date.now
  },
  isActive: Boolean,
  hobbies: [String]
});

Schema支持多种数据类型:

  • String, Number, Boolean, Date
  • Buffer (二进制数据)
  • Mixed (任意类型)
  • ObjectId (引用其他文档)
  • Array (包含特定类型的数组)

模型与文档操作

将Schema编译为Model后,就可以进行CRUD操作了:

const User = mongoose.model('User', userSchema);

// 创建文档
const newUser = new User({
  username: 'devuser',
  email: 'dev@example.com',
  age: 25
});

// 保存文档
newUser.save()
  .then(doc => console.log(doc))
  .catch(err => console.error(err));

// 查询文档
User.findOne({ username: 'devuser' })
  .then(user => console.log(user))
  .catch(err => console.error(err));

Model提供了丰富的查询方法:

  • find(): 查询多个文档
  • findOne(): 查询单个文档
  • findById(): 通过ID查询
  • countDocuments(): 计数
  • updateOne()/updateMany(): 更新文档
  • deleteOne()/deleteMany(): 删除文档

高级查询功能

Mongoose的查询构建器支持链式调用和丰富的操作符:

// 链式查询
User.find()
  .where('age').gte(18).lte(30)
  .where('isActive').equals(true)
  .sort('-createdAt')
  .limit(10)
  .select('username email')
  .exec()
  .then(users => console.log(users));

支持的操作符包括:

  • 比较操作符:$gt, $gte, $lt, $lte, $ne
  • 逻辑操作符:$and, $or, $not, $nor
  • 数组操作符:$in, $nin, $all
  • 元素操作符:$exists, $type

数据验证

Mongoose提供了强大的内置验证器:

const productSchema = new Schema({
  name: { type: String, required: true },
  price: {
    type: Number,
    required: true,
    validate: {
      validator: function(v) {
        return v > 0;
      },
      message: props => `${props.value}不是有效的价格`
    }
  },
  category: {
    type: String,
    enum: ['electronics', 'clothing', 'food']
  }
});

验证类型包括:

  • 必填验证:required
  • 字符串验证:minlength, maxlength, match(正则)
  • 数字验证:min, max
  • 枚举验证:enum
  • 自定义验证:validate

中间件(钩子函数)

Mongoose支持在特定操作前后执行中间件:

userSchema.pre('save', function(next) {
  if (this.isModified('password')) {
    this.password = hashPassword(this.password);
  }
  next();
});

userSchema.post('save', function(doc, next) {
  sendWelcomeEmail(doc.email);
  next();
});

支持的钩子类型:

  • 文档中间件:validate, save, remove
  • 查询中间件:count, find, findOne, update, delete
  • 聚合中间件:aggregate
  • 模型中间件:insertMany

虚拟属性

虚拟属性不会存入数据库,但可以像普通属性一样访问:

userSchema.virtual('fullName').get(function() {
  return `${this.firstName} ${this.lastName}`;
});

userSchema.virtual('fullName').set(function(name) {
  const [firstName, lastName] = name.split(' ');
  this.firstName = firstName;
  this.lastName = lastName;
});

数据填充(Population)

Mongoose可以自动填充文档引用:

const storySchema = new Schema({
  author: { type: Schema.Types.ObjectId, ref: 'User' },
  title: String
});

Story.findOne({ title: 'Mongoose Guide' })
  .populate('author')
  .exec()
  .then(story => console.log(story.author.username));

填充选项包括:

  • 选择填充字段:populate('field', 'name email')
  • 多级填充:populate({ path: 'field', populate: { path: 'nested' } })
  • 条件填充:populate({ path: 'field', match: { age: { $gt: 18 } } })

插件系统

Mongoose支持通过插件扩展功能:

function timestampPlugin(schema) {
  schema.add({ 
    createdAt: Date,
    updatedAt: Date
  });

  schema.pre('save', function(next) {
    const now = new Date();
    this.updatedAt = now;
    if (!this.createdAt) {
      this.createdAt = now;
    }
    next();
  });
}

userSchema.plugin(timestampPlugin);

常用插件:

  • mongoose-autopopulate: 自动填充引用
  • mongoose-paginate: 分页支持
  • mongoose-unique-validator: 唯一性验证
  • mongoose-timestamp: 自动时间戳

事务支持

Mongoose支持MongoDB的事务操作:

const session = await mongoose.startSession();
session.startTransaction();

try {
  const user = await User.create([{ username: 'txuser' }], { session });
  await Account.create([{ userId: user[0]._id, balance: 100 }], { session });
  await session.commitTransaction();
} catch (error) {
  await session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

性能优化

Mongoose提供了多种性能优化手段:

  1. 查询优化:
// 只选择需要的字段
User.find().select('username email');

// 使用lean()返回普通JS对象
User.find().lean();
  1. 批量操作:
// 批量插入
User.insertMany([user1, user2, user3]);

// 批量更新
User.updateMany({ isActive: false }, { $set: { status: 'inactive' } });
  1. 索引支持:
userSchema.index({ username: 1 }, { unique: true });
userSchema.index({ email: 1, status: 1 });

聚合框架集成

Mongoose完全支持MongoDB的聚合框架:

Order.aggregate([
  { $match: { status: 'completed' } },
  { $group: {
    _id: '$customer',
    total: { $sum: '$amount' },
    count: { $sum: 1 }
  }},
  { $sort: { total: -1 } },
  { $limit: 10 }
]);

多数据库连接

Mongoose支持同时连接多个数据库:

const conn1 = mongoose.createConnection('mongodb://localhost/db1');
const conn2 = mongoose.createConnection('mongodb://localhost/db2');

const Model1 = conn1.model('Model', schema);
const Model2 = conn2.model('Model', schema);

类型转换与自定义类型

Mongoose支持自定义类型和类型转换:

function toLower(v) {
  return v.toLowerCase();
}

const emailSchema = new Schema({
  email: {
    type: String,
    set: toLower
  }
});

// 自定义类型
class Money extends mongoose.SchemaType {
  constructor(key, options) {
    super(key, options, 'Money');
  }
  cast(val) {
    return parseFloat(val).toFixed(2);
  }
}

mongoose.Schema.Types.Money = Money;

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌