1️⃣ 数据结构
2️⃣ 创建的索引
3️⃣ 查询
👉 你希望它走 覆盖索引(即查询结果只来自索引,而不用回表)。
但是它没法覆盖,原因在于:
4️⃣ 为什么不能覆盖?
-
多键索引限制
-
由于
event
是数组字段,MongoDB 自动生成 多键索引。 -
覆盖查询的前提是:查询返回的字段必须完全来自索引。
-
在多键索引里,MongoDB 无法保证返回的 数组内容 和原文档一一对应,所以它拒绝覆盖查询,必须回表确认。
👉 换句话说,多键索引不能用于 covered query。
-
-
索引字段不匹配返回字段
-
你的索引是
{ event: 1, name: 1 }
,包含event
和name
。 -
查询返回
{event}
,理论上可以覆盖,但因为event
是数组 → 失效。
-
5️⃣ 解决方案
✅ 方法 1:把数组字段拆表
如果你需要覆盖查询,最好不要直接对数组字段建索引,而是把数组展开存储到另一张集合:
索引:
查询:
👉 现在可以覆盖索引了。
✅ 方法 2:只给 event
建单字段索引(但仍然不能覆盖)
查询:
👉 虽然能用到索引,但 不会覆盖,因为 event
是数组。
6️⃣ 结论
-
根本原因:多键索引(数组字段索引)不支持覆盖查询。
-
想要覆盖查询 → 必须把数组拆分成独立文档。
-
如果只是为了加速查询,不在乎覆盖 → 单字段或复合索引就够了。
✅ 建议:
-
高性能查询(尤其是只查索引字段) → 不要直接对数组字段依赖覆盖索引,最好设计成“子集合”。
-
标签 / 分类这种小数组 → 普通多键索引就够了,不强求覆盖。