通配符索引仅对路径明确且字段动态的等值或前缀查询有效,需显式写出完整字段路径并使用$eq、$in、$gt等b-tree可下推操作符,不支持模糊搜索、文本搜索、数组展开及默认_id查询。

通配符索引只对「路径明确 + 字段动态」的等值或前缀查询有效,不是模糊搜索加速器,也不是通用索引替代品。
哪些查询能真正走通配符索引
通配符索引({"metadata.$**": 1} 或 {"$**": 1})仅在查询条件中**显式写出字段完整路径**,且操作符是 $eq、$in、$gt 等 B-tree 可下推类型时才生效:
-
db.items.find({"metadata.color": "blue"})→ ✅ 走索引(路径固定、等值) -
db.items.find({"metadata.version": {"$gte": "2.1"}})→ ✅ 走索引(路径固定、范围) -
db.items.find({"customFields.addr": "Beijing"})→ ✅ 若建了{"customFields.$**": 1} -
db.items.find({"tags": {"$in": ["a", "b"]}})→ ❌ 不走,除非tags是通配路径下的子字段(如metadata.tags),且索引覆盖它
哪些常见查询它完全不加速
通配符索引对以下场景无优化效果,强行依赖会导致全表扫描:
-
name: {$regex: ".*liu.*"}或name: {$regex: /liu/i}→ ❌ 左/右/全模糊都不行;只有^Alice这种前缀固定、无i标志才可能走普通索引 -
desc: {$text: {$search: "fast"}}→ ❌ 文本搜索必须用text索引,通配符不支持$text -
tags: {$in: ["x", "y"]}(tags是顶层数组)→ ❌ 通配符不展开数组内容,“tags.$**” 是非法语法 -
{"_id": ObjectId("...")}→ ❌ 默认不索引_id,即使建了{"$**": 1};需显式加wildcardProjection: {"_id": 1}
复合通配符索引的关键约束
想把通配和固定字段组合(比如 tenantId + metadata),必须守死三条线:
- 一个索引里最多只能有一个通配符项,例如
{"tenantId": 1, "metadata.$**": 1}✅,但{"a.$**": 1, "b.$**": 1}❌ 报错 - 非通配字段必须是单键,不能是多键字段(如数组字段直接作为非通配项会触发限制)
-
wildcardProjection只在"$**"全局通配时可用;"metadata.$**"这类局部通配不支持该选项
最容易被忽略的性能陷阱
通配符索引生效不等于高效——它容易在三个地方悄悄拖垮系统:
- 索引体积膨胀:每个嵌套字段都单独建条目,
{"a": {"b": {"c": 1, "d": 2}}}会生成a.b.c、a.b.d两条索引记录,字段越深越多 - 低选择性放大开销:如果
metadata.status大部分是"active",索引虽命中却仍要扫大量文档 - 无法投影(
$project):即使只查metadata.color,MongoDB 仍可能加载整个metadata子文档,内存压力陡增
真正要用,得先压测真实查询的 explain("executionStats") 输出,确认 nReturned 和 totalDocsExamined 接近,而不是只看 indexName 出现了就以为万事大吉。











