mongoose入门教程

以下是详细的 Mongoose 入门教程,包含代码示例和关键概念说明:


1. 环境准备

安装依赖

npm install mongoose

启动 MongoDB 服务

本地安装或使用 MongoDB Atlas 云服务


2. 基本连接

const mongoose = require('mongoose');

// 基础连接
mongoose.connect('mongodb://localhost:27017/mydb')
  .then(() => console.log('Connected to MongoDB'))
  .catch(err => console.error('Connection failed:', err));

// 带配置的连接
mongoose.connect('mongodb://localhost:27017/mydb', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  serverSelectionTimeoutMS: 5000
});

3. Schema 定义

基本字段类型

const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    minlength: 3,
    maxlength: 20
  },
  age: {
    type: Number,
    min: 18,
    max: 100
  },
  createdAt: {
    type: Date,
    default: Date.now
  },
  hobbies: [String], // 字符串数组
  address: {
    street: String,
    city: String
  }
});

自定义验证

const productSchema = new mongoose.Schema({
  price: {
    type: Number,
    validate: {
      validator: function(v) {
        return v >= this.costPrice; // 售价必须大于成本价
      },
      message: props => `售价 ${props.value} 不能低于成本价`
    }
  },
  costPrice: Number
});

4. 创建模型

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

5. CRUD 操作

创建文档

const newUser = new User({
  username: 'john_doe',
  age: 25,
  hobbies: ['reading', 'coding']
});

// 保存方式1
const savedUser = await newUser.save();

// 保存方式2
await User.create({
  username: 'jane_smith',
  age: 30
});

查询文档

// 基础查询
const users = await User.find({ age: { $gt: 20 } });

// 链式查询
const user = await User.findOne({ username: 'john_doe' })
  .select('username age')
  .sort('-age')
  .limit(5);

更新文档

// 直接更新
await User.updateOne(
  { username: 'john_doe' },
  { $set: { age: 26 } }
);

// 先查询后保存
const user = await User.findById('...');
user.age = 26;
await user.save();

删除文档

await User.deleteOne({ _id: '...' });
await User.findByIdAndDelete('...');

6. 中间件(Hooks)

pre 保存钩子

userSchema.pre('save', function(next) {
  if (this.isNew) {
    this.createdAt = Date.now();
  }
  next();
});

post 查询钩子

userSchema.post('find', function(docs) {
  console.log(`查询到 ${docs.length} 个用户`);
});

7. 关联查询

定义关联模型

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

填充查询

const posts = await Post.find()
  .populate('author', 'username')
  .exec();

8. 聚合查询

const result = await User.aggregate([
  { $match: { age: { $gt: 20 } } },
  { $group: { 
    _id: "$city",
    averageAge: { $avg: "$age" }
  }}
]);

9. 错误处理

try {
  await User.create({ age: 17 }); // 触发最小年龄验证
} catch (err) {
  if (err instanceof mongoose.Error.ValidationError) {
    console.log('验证错误:', err.message);
  }
}

10. 最佳实践

  1. 连接管理
// 连接状态监控
mongoose.connection.on('connected', () => console.log('MongoDB connected'));
mongoose.connection.on('error', (err) => console.error('MongoDB error', err));
mongoose.connection.on('disconnected', () => console.log('MongoDB disconnected'));
  1. 全局插件
// 为所有 Schema 添加时间戳
mongoose.plugin((schema) => {
  schema.add({ 
    createdAt: { type: Date, default: Date.now },
    updatedAt: { type: Date, default: Date.now }
  });
  
  schema.pre('save', function(next) {
    this.updatedAt = Date.now();
    next();
  });
});

11. 调试模式

// 查看所有执行的查询
mongoose.set('debug', true);

12. 性能优化

索引创建

userSchema.index({ username: 1 }, { unique: true });
userSchema.index({ age: 1, city: 1 });

查询优化

// 仅返回需要字段
await User.find().select('username');

// 限制结果数量
await User.find().limit(100);

13. 完整示例

const mongoose = require('mongoose');

// 1. 连接数据库
mongoose.connect('mongodb://localhost:27017/mydb');

// 2. 定义 Schema
const bookSchema = new mongoose.Schema({
  title: { type: String, required: true },
  author: String,
  price: Number,
  published: Boolean
});

// 3. 创建模型
const Book = mongoose.model('Book', bookSchema);

// 4. 业务操作
async function main() {
  // 创建
  const book = await Book.create({
    title: 'Node.js实战',
    author: '张三',
    price: 59.9,
    published: true
  });

  // 查询
  const foundBook = await Book.findById(book._id);
  
  // 更新
  await Book.updateOne(
    { _id: book._id },
    { $set: { price: 69.9 } }
  );

  // 删除
  await Book.deleteOne({ _id: book._id });
}

main().catch(err => console.error(err));

常见问题解答

  1. 连接池配置
mongoose.connect(uri, {
  poolSize: 10, // 最大连接数
  socketTimeoutMS: 45000
});
  1. 时区处理
const date = new Date().toLocaleString('zh-CN', { 
  timeZone: 'Asia/Shanghai' 
});
  1. 批量操作
await User.insertMany([
  { username: 'user1', age: 25 },
  { username: 'user2', age: 30 }
]);

通过这个教程,你可以掌握 Mongoose 的核心用法。建议配合官方文档 (https://mongoosejs.com/) 深入学习高级特性。

posted @ 2025-03-14 16:22  jintaonote  阅读(849)  评论(0)    收藏  举报