Skip to content

MongoDB - 高级索引

除了单字段索引,MongoDB 还提供了各种强大的索引类型来优化复杂的查询。本章涵盖了嵌入式文档和数组(多键索引)上的索引,并介绍了其他专用索引类型。

我们来使用 products 集合中的一个示例文档:

db.products.insertOne({
"name": "Wireless Keyboard",
"inventory": {
"warehouse": "A",
"quantity": 45
},
"tags": ["electronics", "computer", "accessories"],
"ratings": [5, 4, 5, 5, 4]
})

为了优化对嵌入式文档中字段的查询,您在 createIndex 命令中使用“点表示法”。这允许您直接指定嵌套字段。

// Create an index on the 'quantity' field inside the 'inventory' sub-document
db.products.createIndex({ "inventory.quantity": -1 }) // -1 for descending order

此索引将高效地服务于按库存数量筛选或排序的查询:

// This query can use the index to find low-stock items quickly
db.products.find({ "inventory.quantity": { $lt: 10 } })

当您在包含数组值的字段上创建索引时,MongoDB 会创建一个“多键索引”。它会为数组中的每个元素添加一个索引键。这允许高效查询以查找数组字段包含特定值的文档。

// Create a multikey index on the 'tags' array
db.products.createIndex({ tags: 1 })

此索引允许 MongoDB 快速查找所有带有“computer”标签的产品:

> db.products.find({ tags: "computer" }).explain('executionStats')
// The explain plan's winningPlan will show an IXSCAN on the tags_1 index.
// It will also indicate 'isMultiKey: true'.

MongoDB 支持其他几种专用索引类型以适应不同的用例:

  • 复合索引:在多个字段上创建的索引。复合索引中字段的顺序非常重要,因为它决定了该索引可以支持哪些查询。我们“覆盖查询”示例中的 { status: 1, username: 1 } 就是一个复合索引。
  • 文本索引:用于搜索集合中的字符串内容。它们支持特定语言的停用词和词干提取。一个集合最多只能有一个文本索引。
  • 地理空间索引:用于优化对位置数据(例如经度、纬度)的查询。它们允许您查找某个半径内、多边形内的点,或查找距离某个位置最近的点。
  • TTL(存活时间)索引:一种特殊的单字段索引,允许您在经过一定时间后自动从集合中删除文档。非常适用于会话数据、日志或任何临时信息。

创建复合索引时,请遵循 ESR(Equality, Sort, Range - 相等、排序、范围)规则:用于精确匹配的字段应放在首位,其次是用于排序的字段,最后是用于范围查询的字段。

创建索引以支持您的应用程序的特定查询。使用数据库分析器(Database Profiler)或 .explain() 分析慢查询,以识别缺失的索引。请记住,虽然索引极大地加快了读取速度,但它们会给写入操作带来少量开销,因此请避免创建从不使用的索引。