第四章 索引与聚合 v1.0
一、索引
索引是特殊的数据结构,存储集合中一小部分数据集的有序表示,用于提高查询效率。
1.创建索引
javascript
// 创建单字段索引(1为升序,-1为降序)
db.users.createIndex({ name: 1 })
// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
// 创建复合索引
db.users.createIndex({ name: 1, age: -1 })
// 创建文本索引(用于全文搜索)
db.articles.createIndex({ title: "text", content: "text" })2.查看索引
javascript
// 查看集合的所有索引
db.users.getIndexes()
// 查看索引大小
db.users.totalIndexSize()3.删除索引
javascript
// 删除指定索引
db.users.dropIndex({ name: 1 })
// 删除所有索引(_id索引除外)
db.users.dropIndexes()4.索引类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| 单字段索引 | 单个字段的升序/降序 | 最常见的查询优化 |
| 复合索引 | 多个字段组合 | 多条件查询 |
| 唯一索引 | 确保字段值唯一 | 邮箱、用户名等 |
| 文本索引 | 全文搜索 | 文章内容搜索 |
| 哈希索引 | 基于哈希值 | 等值查询、分片 |
| TTL索引 | 自动过期删除 | 日志、Session |
| 多键索引 | 数组字段 | 数组类型的字段 |
二、聚合(Aggregation)
聚合管道将文档通过多个阶段(Stage)进行处理,每个阶段的输出作为下一个阶段的输入。
1.常用阶段
javascript
// $match:过滤文档(类似find)
db.users.aggregate([{ $match: { age: { $gte: 18 } } }])
// $group:分组统计
db.users.aggregate([
{ $group: { _id: "$city", count: { $sum: 1 }, avgAge: { $avg: "$age" } } }
])
// $sort:排序
db.users.aggregate([{ $sort: { age: -1 } }])
// $limit / $skip:分页
db.users.aggregate([{ $skip: 10 }, { $limit: 5 }])
// $project:字段投影
db.users.aggregate([
{ $project: { name: 1, age: 1, isAdult: { $gte: ["$age", 18] } } }
])
// $lookup:关联查询(类似SQL的JOIN)
db.orders.aggregate([
{
$lookup: {
from: "users",
localField: "userId",
foreignField: "_id",
as: "user"
}
}
])2.常用累加器
| 操作符 | 说明 | 示例 |
|---|---|---|
| $sum | 求和 | { $sum: "$price" } |
| $avg | 平均值 | { $avg: "$score" } |
| $max | 最大值 | { $max: "$age" } |
| $min | 最小值 | { $min: "$age" } |
| $push | 收集为数组 | { $push: "$name" } |
| $first | 第一个值 | { $first: "$name" } |
| $last | 最后一个值 | { $last: "$name" } |
| $addToSet | 去重收集 | { $addToSet: "$tag" } |
3.聚合示例
javascript
// 按城市统计用户数和平均年龄,按用户数降序排列
db.users.aggregate([
{ $group: { _id: "$city", count: { $sum: 1 }, avgAge: { $avg: "$age" } } },
{ $sort: { count: -1 } }
])
// 统计每个用户的订单总金额
db.orders.aggregate([
{ $group: { _id: "$userId", totalAmount: { $sum: "$amount" } } },
{ $lookup: { from: "users", localField: "_id", foreignField: "_id", as: "user" } },
{ $unwind: "$user" },
{ $project: { userName: "$user.name", totalAmount: 1 } }
])