1️⃣ 数据模型(video 文档)

{ "_id": ObjectId("..."), "title": "星际穿越", "category": ["战争", "科幻", "故事"], // 多个分类 "popularity": 98765, // 人气 "publish_time": ISODate("2023-01-01") // 发布时间 }

2️⃣ 查询需求

按分类查询,并且支持 按人气和发布时间排序

示例:

db.videos.find( { category: "科幻" } ).sort({ popularity: -1, publish_time: -1 })

3️⃣ 索引设计思路

(1) category 是数组 → 多键索引

category 建索引时,MongoDB 会自动展开,支持类似:

db.videos.find({ category: "科幻" })

(2) 排序字段需要在索引中

MongoDB 能利用索引加速排序,前提是排序字段 包含在索引里,并且符合 最左前缀规则

所以我们需要一个复合索引:

db.videos.createIndex({ category: 1, popularity: -1, publish_time: -1 })

4️⃣ 查询效果

  • category 精确匹配 + 按人气、发布时间排序

    db.videos.find({ category: "科幻" }) .sort({ popularity: -1, publish_time: -1 })

    ✅ 能完全走索引。

  • 只查某个分类(不排序)

    db.videos.find({ category: "战争" })

    ✅ 能走索引(用到最左前缀)。

  • 只按人气/时间排序,不筛选分类

    db.videos.find().sort({ popularity: -1, publish_time: -1 })

    ❌ 不能用这个索引(因为 category 在前,必须有条件才会利用)。
    👉 如果有这种需求,可以额外建一个:

    db.videos.createIndex({ popularity: -1, publish_time: -1 })

5️⃣ ⚠️ 注意事项

  1. 多键索引限制

    • category 是数组,category + popularity + publish_time 会变成 多键复合索引

    • 允许,但要注意数组过大(几十上百个元素)时索引膨胀,性能下降。

  2. 复合索引顺序很重要

    • 你先过滤分类,再排序 → 所以 category 必须在最前面。

  3. 查询模式要固定

    • 如果有时要 category+popularity,有时要 category+publish_time,最好各建一个复合索引。

    • 否则会导致索引不能完全利用。


6️⃣ 推荐索引方案

如果主要需求是:

  • 按分类筛选 + 人气/时间排序 → 一个复合索引就够:

    db.videos.createIndex({ category: 1, popularity: -1, publish_time: -1 })

如果还经常需要:

  • 全站按人气/时间排序 → 额外再建一个:

    db.videos.createIndex({ popularity: -1, publish_time: -1 })

✅ 总结:

  • 分类字段数组可以直接存,MongoDB 会自动做多键索引。

  • 查询时要排序,必须把排序字段加到复合索引里。

  • 最合适的索引是:

    { category: 1, popularity: -1, publish_time: -1 }
  • 如果还要支持全站排序,则额外加 { popularity: -1, publish_time: -1 }

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部