1.23Node.js 中操作 mongodb

Mongoose是Node.js 操作 MongoDB 的优雅解决方案

Mongoose 是一个基于 Node.js 的 MongoDB 对象建模工具,它为 Node.js 与 MongoDB 之间提供了一个高级抽象层,使开发者可以更便捷地操作 MongoDB。

1. 安装与基本设置

首先安装 Mongoose:

复制代码
npm install mongoose

连接到 MongoDB 数据库:

复制代码
const mongoose = require('mongoose');

async function connectDB() {
  try {
    await mongoose.connect('mongodb://localhost:27017/mydatabase', {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useCreateIndex: true,
      useFindAndModify: false
    });
    console.log('Connected to MongoDB');
  } catch (error) {
    console.error('Error connecting to MongoDB:', error);
    process.exit(1);
  }
}

connectDB();

2. 核心概念:Schema、Model 和 Document

Schema(模式)

定义数据结构和验证规则:

复制代码
const mongoose = require('mongoose');
const { Schema } = mongoose;

const userSchema = new Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  email: {
    type: String,
    required: true,
    unique: true,
    lowercase: true,
    validate: {
      validator: (value) => {
        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
      },
      message: 'Invalid email address'
    }
  },
  age: {
    type: Number,
    min: 1,
    max: 150
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});
Model(模型)

基于 Schema 创建数据模型:

复制代码
const User = mongoose.model('User', userSchema);
Document(文档)

模型的实例,代表 MongoDB 中的一个文档:

复制代码
const newUser = new User({
  name: 'John Doe',
  email: 'john@example.com',
  age: 30
});

newUser.save()
  .then(user => console.log('User saved:', user))
  .catch(error => console.error('Error saving user:', error));

3. 数据验证

Mongoose 提供内置和自定义验证器:

复制代码
const productSchema = new Schema({
  name: {
    type: String,
    required: [true, 'Product name is required'],
    minlength: [3, 'Name must be at least 3 characters']
  },
  price: {
    type: Number,
    required: true,
    validate: {
      validator: (value) => value > 0,
      message: 'Price must be greater than 0'
    }
  },
  category: {
    type: String,
    enum: {
      values: ['electronics', 'clothing', 'books'],
      message: '{VALUE} is not a valid category'
    }
  }
});

4. 数据操作

创建文档
复制代码
// 单个创建
User.create({ name: 'Alice', email: 'alice@example.com', age: 25 })
  .then(user => console.log('Created user:', user))
  .catch(error => console.error('Error creating user:', error));

// 批量创建
User.insertMany([
  { name: 'Bob', email: 'bob@example.com', age: 30 },
  { name: 'Charlie', email: 'charlie@example.com', age: 35 }
])
  .then(users => console.log('Created users:', users))
  .catch(error => console.error('Error creating users:', error));
查询文档
复制代码
// 查找所有用户
User.find()
  .then(users => console.log('All users:', users))
  .catch(error => console.error('Error finding users:', error));

// 按条件查找
User.findOne({ age: { $gte: 30 } })
  .then(user => console.log('User over 30:', user))
  .catch(error => console.error('Error finding user:', error));

// 按 ID 查找
User.findById('6123456789abcdef12345678')
  .then(user => console.log('User by ID:', user))
  .catch(error => console.error('Error finding user by ID:', error));

// 高级查询
User.find()
  .where('age').gte(25).lte(40)
  .sort('-age')
  .select('name email')
  .limit(10)
  .then(users => console.log('Filtered users:', users))
  .catch(error => console.error('Error filtering users:', error));
更新文档
复制代码
// 按 ID 更新
User.findByIdAndUpdate(
  '6123456789abcdef12345678',
  { age: 31 },
  { new: true, runValidators: true }
)
  .then(updatedUser => console.log('Updated user:', updatedUser))
  .catch(error => console.error('Error updating user:', error));

// 按条件更新
User.updateOne(
  { email: 'john@example.com' },
  { $set: { name: 'John Smith' } }
)
  .then(result => console.log('Update result:', result))
  .catch(error => console.error('Error updating user:', error));
删除文档
复制代码
// 按 ID 删除
User.findByIdAndDelete('6123456789abcdef12345678')
  .then(deletedUser => console.log('Deleted user:', deletedUser))
  .catch(error => console.error('Error deleting user:', error));

// 按条件删除
User.deleteMany({ age: { $lt: 25 } })
  .then(result => console.log('Deleted users:', result.deletedCount))
  .catch(error => console.error('Error deleting users:', error));

5. 中间件(Middleware)

在文档操作前后执行自定义逻辑:

复制代码
// 保存前的中间件
userSchema.pre('save', function(next) {
  // 对密码进行哈希处理
  if (this.isModified('password')) {
    this.password = bcrypt.hashSync(this.password, 10);
  }
  next();
});

// 保存后的中间件
userSchema.post('save', function(doc, next) {
  console.log('User saved:', doc._id);
  next();
});

// 查询后的中间件
userSchema.post('find', function(docs, next) {
  console.log(`Returned ${docs.length} users`);
  next();
});

6. 虚拟字段(Virtuals)

定义不存储在数据库中的计算字段:

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

userSchema.virtual('isAdult').get(function() {
  return this.age >= 18;
});

// 使用虚拟字段
User.findOne({ email: 'john@example.com' })
  .then(user => {
    console.log('Full name:', user.fullName);
    console.log('Is adult:', user.isAdult);
  })
  .catch(error => console.error('Error fetching user:', error));

7. 关联(Population)

处理文档间的关系:

复制代码
// 定义作者模式
const authorSchema = new Schema({
  name: String,
  country: String
});

// 定义书籍模式
const bookSchema = new Schema({
  title: String,
  author: {
    type: Schema.Types.ObjectId,
    ref: 'Author'
  }
});

// 关联查询
Book.findOne({ title: 'Mongoose Guide' })
  .populate('author', 'name country -_id') // 选择要返回的字段
  .then(book => console.log('Book with author:', book))
  .catch(error => console.error('Error fetching book:', error));

8. 聚合(Aggregation)

执行复杂的数据处理:

复制代码
User.aggregate([
  // 匹配年龄大于25的用户
  { $match: { age: { $gt: 25 } } },
  
  // 按国家分组并计算每组的平均年龄和用户数
  { $group: {
    _id: '$country',
    averageAge: { $avg: '$age' },
    count: { $sum: 1 }
  } },
  
  // 按平均年龄降序排序
  { $sort: { averageAge: -1 } },
  
  // 限制结果数量
  { $limit: 5 }
])
  .then(results => console.log('Aggregation results:', results))
  .catch(error => console.error('Error in aggregation:', error));

Mongoose 为 MongoDB 提供了强大而灵活的抽象层,使 Node.js 开发者能够更高效地处理数据库操作,同时保持代码的整洁和可维护性。通过合理使用 Schema、Model、验证、中间件等特性,可以构建出健壮的数据库层。

相关推荐
秉承初心22 分钟前
Node.js 开发 JavaScript SDK 包的完整指南(AI)
开发语言·javascript·node.js
孙霸天3 小时前
Ubuntu20系统上离线安装MongoDB
数据库·mongodb·ubuntu·备份还原
Java 码农3 小时前
nodejs mongodb基础
数据库·mongodb·node.js
天天进步20156 小时前
Node.js中Express框架入门教程
node.js·express
满目8287 小时前
MongoDB 从入门到实践:全面掌握文档型 NoSQL 数据库核心操作
数据库·mongodb·非关系型数据库·文档型数据库·基础查询命令·进阶查询
爱心发电丶11 小时前
NodeSSh 实现前端自动部署:服务端编译和本地编译
node.js
Face11 小时前
Node.js全栈基石(壹)
前端·node.js
mosen86813 小时前
易混淆的CommonJS和ESM(ES Module)及它们区别
javascript·node.js·express
袁袁袁袁满1 天前
基于nvm安装管理多个node.js版本切换使用(附上详细安装使用图文教程+nvm命令大全)
运维·node.js·nvm·nvm安装·多个node.js版本切换使用·nvm命令大全·node.js安装
郭京京1 天前
mongodb基础
mongodb·go