使用 Mongoose 实现 MongoDB-Node.js 操作实战(二)

在上一篇文章中,我们介绍了如何使用 Mongoose 连接 MongoDB 数据库,并进行基本的增删改查操作。本文将继续介绍 Mongoose 的高级用法,包括数据校验、中间件、聚合操作等。

数据校验

在进行数据操作时,我们经常需要对数据进行校验,以确保数据的有效性和完整性。Mongoose 提供了丰富的数据校验功能,可以在模型定义时进行配置。

基本校验

Mongoose 内置了许多基本的校验器,可以用于对字段进行校验。例如,我们可以使用 required 校验器来确保字段不为空:

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  age: Number
});

上述代码定义了一个用户模型,其中 name 字段必须存在,否则会抛出错误。

除了 required 校验器,Mongoose 还提供了许多其他校验器,例如 minmaxenum 等,可以根据具体的需求进行配置。

自定义校验

如果内置校验器无法满足需求,我们还可以自定义校验器。自定义校验器需要定义一个函数,接受字段值作为参数,并返回布尔值表示校验结果。例如,我们可以定义一个校验器,确保用户年龄大于等于 18:

const userSchema = new mongoose.Schema({
  name: String,
  age: {
    type: Number,
    validate: {
      validator: function(v) {
        return v >= 18;
      },
      message: 'Age must be greater than or equal to 18'
    }
  }
});

上述代码定义了一个用户模型,其中 age 字段必须大于等于 18,否则会抛出错误。

中间件

Mongoose 还提供了中间件功能,可以在数据操作前后执行一些额外的逻辑。中间件可以分为两种类型:前置中间件和后置中间件。

前置中间件

前置中间件会在数据操作前执行,可以用于做一些数据预处理或校验。例如,我们可以在保存用户数据前对密码进行加密:

userSchema.pre('save', function(next) {
  const user = this;
  if (!user.isModified('password')) {
    return next();
  }
  bcrypt.genSalt(10, function(err, salt) {
    if (err) {
      return next(err);
    }
    bcrypt.hash(user.password, salt, function(err, hash) {
      if (err) {
        return next(err);
      }
      user.password = hash;
      next();
    });
  });
});

上述代码定义了一个前置中间件,当保存用户数据时会先对密码进行加密。其中 isModified 方法用于判断字段是否被修改过,以避免重复加密。

后置中间件

后置中间件会在数据操作后执行,可以用于做一些数据清理或日志记录。例如,我们可以在删除用户数据后删除其头像文件:

userSchema.post('remove', function(doc, next) {
  const avatarPath = path.join(__dirname, 'avatars', doc._id + '.jpg');
  fs.unlink(avatarPath, function(err) {
    if (err) {
      return next(err);
    }
    next();
  });
});

上述代码定义了一个后置中间件,当删除用户数据后会先删除其头像文件。其中 doc 参数表示被删除的文档对象。

聚合操作

除了基本的增删改查操作,Mongoose 还支持丰富的聚合操作,可以用于分析数据或生成报表。聚合操作需要使用 aggregate 方法,可以链式调用多个聚合操作。例如,我们可以统计每个用户的文章数量:

const pipeline = [
  { $match: { user: userId } },
  { $group: { _id: '$user', count: { $sum: 1 } } }
];
Article.aggregate(pipeline).exec(function(err, result) {
  if (err) {
    console.error(err);
  } else {
    console.log(result);
  }
});

上述代码定义了一个聚合操作,首先使用 $match 操作筛选出指定用户的文章,然后使用 $group 操作对用户进行分组,并计算每个组内的文章数量。

总结

本文介绍了 Mongoose 的高级用法,包括数据校验、中间件、聚合操作等。这些功能可以帮助我们更好地管理和分析数据,提高代码的可维护性和可扩展性。在实际开发中,我们应根据具体需求灵活使用这些功能,以提高开发效率和代码质量。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6587be73eb4cecbf2dcfeee8


纠错
反馈