MongoDB 入门与实践指南

MongoDB 基础概念

MongoDB是一个面向文档的NoSQL数据库,使用BSON(二进制JSON)格式存储数据。与传统的关系型数据库相比,MongoDB具有更好的扩展性和灵活性。

基本概念对比

// MongoDB vs SQL 术语对比
// 数据库 -> 数据库
// 集合 -> 表
// 文档 -> 行
// 字段 -> 列
// 嵌套文档 -> 关联表

// MongoDB文档示例
{
    "_id": ObjectId("507f1f77bcf86cd799439011"),
    "name": "张三",
    "age": 25,
    "email": "zhangsan@example.com",
    "address": {
        "city": "北京",
        "street": "朝阳路123号"
    },
    "hobbies": ["编程", "阅读", "运动"],
    "createdAt": ISODate("2024-01-18T10:30:00Z")
}

CRUD 操作

1. 创建文档

// 插入单个文档
db.users.insertOne({
    name: "李四",
    age: 30,
    email: "lisi@example.com",
    isActive: true
});

// 插入多个文档
db.users.insertMany([
    { name: "王五", age: 28, role: "admin" },
    { name: "赵六", age: 35, role: "user" }
]);

2. 查询文档

// 查询所有文档
db.users.find();

// 带条件查询
db.users.find({ age: { $gt: 25 } }); // 年龄大于25
db.users.find({ role: "admin", isActive: true }); // 多个条件

// 查询操作符
db.users.find({ age: { $in: [25, 30, 35] } }); // 年龄在数组中
db.users.find({ name: { $regex: /^张/ } }); // 正则表达式匹配

// 投影(选择字段)
db.users.find({}, { name: 1, email: 1 }); // 只返回name和email字段

// 排序和限制
db.users.find().sort({ age: -1 }).limit(10); // 按年龄降序,限制10条

3. 更新文档

// 更新单个文档
db.users.updateOne(
    { name: "张三" },
    { $set: { age: 26, updatedAt: new Date() } }
);

// 更新多个文档
db.users.updateMany(
    { role: "user" },
    { $set: { isActive: true } }
);

// 更新操作符
db.users.updateOne(
    { name: "张三" },
    { 
        $inc: { age: 1 }, // 年龄加1
        $push: { hobbies: "游泳" }, // 数组添加元素
        $set: { lastLogin: new Date() }
    }
);

4. 删除文档

// 删除单个文档
db.users.deleteOne({ name: "张三" });

// 删除多个文档
db.users.deleteMany({ isActive: false });

// 删除所有文档(清空集合)
db.users.deleteMany({});

聚合管道

聚合管道是MongoDB中强大的数据处理工具,可以对数据进行多阶段的转换和处理。

// 示例:统计用户年龄分布
db.users.aggregate([
    // 阶段1: 匹配条件
    { $match: { isActive: true } },
    
    // 阶段2: 按年龄段分组
    { 
        $bucket: {
            groupBy: "$age",
            boundaries: [0, 20, 30, 40, 50, 100],
            default: "其他",
            output: {
                count: { $sum: 1 },
                averageScore: { $avg: "$score" },
                users: { $push: "$name" }
            }
        }
    },
    
    // 阶段3: 排序
    { $sort: { count: -1 } },
    
    // 阶段4: 限制结果数量
    { $limit: 10 }
]);

// 常用聚合操作符
// $match: 过滤文档
// $group: 分组聚合
// $sort: 排序
// $project: 字段投影
// $limit: 限制数量
// $skip: 跳过文档
// $lookup: 连接查询

索引优化

// 创建索引
db.users.createIndex({ email: 1 }); // 单字段索引
db.users.createIndex({ name: 1, age: -1 }); // 复合索引
db.users.createIndex({ location: "2dsphere" }); // 地理空间索引
db.users.createIndex({ content: "text" }); // 全文索引

// 查看索引
db.users.getIndexes();

// 删除索引
db.users.dropIndex("email_1");

// 索引使用情况
db.users.find({ email: "test@example.com" }).explain("executionStats");

Node.js中的MongoDB操作

// 使用Mongoose ODM
const mongoose = require('mongoose');

// 定义Schema
const userSchema = new mongoose.Schema({
    name: { type: String, required: true },
    email: { 
        type: String, 
        required: true, 
        unique: true,
        match: /^\S+@\S+\.\S+$/
    },
    age: { type: Number, min: 0, max: 120 },
    address: {
        city: String,
        street: String,
        postalCode: String
    },
    hobbies: [String],
    createdAt: { type: Date, default: Date.now }
});

// 创建模型
const User = mongoose.model('User', userSchema);

// 连接数据库
mongoose.connect('mongodb://localhost:27017/mydb', {
    useNewUrlParser: true,
    useUnifiedTopology: true
});

// 创建用户
const newUser = new User({
    name: '王小明',
    email: 'wang@example.com',
    age: 28
});

await newUser.save();

// 查询用户
const users = await User.find({ age: { $gte: 25 } })
    .sort({ createdAt: -1 })
    .limit(10);

最佳实践

  1. 合理设计文档结构:根据查询模式设计文档,避免过度嵌套
  2. 使用适当的索引:为常用查询字段创建索引,但避免过多索引影响写入性能
  3. 数据验证:在应用层和数据库层都进行数据验证
  4. 连接池管理:合理配置连接池大小
  5. 备份策略:定期备份重要数据

MongoDB作为流行的NoSQL数据库,在Web开发中有着广泛的应用。掌握MongoDB的基本操作和高级特性,可以帮助您构建高性能、可扩展的应用程序。