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);
最佳实践
- 合理设计文档结构:根据查询模式设计文档,避免过度嵌套
- 使用适当的索引:为常用查询字段创建索引,但避免过多索引影响写入性能
- 数据验证:在应用层和数据库层都进行数据验证
- 连接池管理:合理配置连接池大小
- 备份策略:定期备份重要数据
MongoDB作为流行的NoSQL数据库,在Web开发中有着广泛的应用。掌握MongoDB的基本操作和高级特性,可以帮助您构建高性能、可扩展的应用程序。