🔹 1. 基础概念回顾

通配符索引($**)会 展开文档里的每一个字段,并对它们建索引。

  • 如果是嵌入文档(object),会递归索引子字段。

  • 如果是数组,会对数组里的每个元素建索引(类似多键索引的规则)。


🔹 2. 对象(嵌入文档)规则

示例数据

{ "name": "iPhone", "attributes": { "screen": "6.1", "battery": "3200mAh", "cpu": "A17" } }

通配符索引

db.products.createIndex({ "attributes.$**": 1 })

索引展开逻辑

MongoDB 会对 attributes 下的每个字段建索引:

"attributes.screen" -> "6.1" "attributes.battery" -> "3200mAh" "attributes.cpu" -> "A17"

✅ 查询:

db.products.find({ "attributes.screen": "6.1" })

能用索引。


🔹 3. 数组规则

示例数据

{ "name": "T-Shirt", "attributes": [ { "color": "black", "size": "XL" }, { "color": "white", "size": "L" } ] }

通配符索引

db.products.createIndex({ "attributes.$**": 1 })

索引展开逻辑

MongoDB 会将数组 作为多键索引展开

"attributes.color" -> "black" "attributes.size" -> "XL" "attributes.color" -> "white" "attributes.size" -> "L"

✅ 查询:

db.products.find({ "attributes.color": "black" })

会命中索引。

⚠️ 但是注意:

db.products.find({ "attributes.color": "black", "attributes.size": "XL" })

👉 MongoDB 不会保证 color=black 和 size=XL 来自同一个对象,可能来自数组的不同元素!
这就是多键索引的限制(会导致 跨元素匹配)。
如果需要“同一元素条件匹配”,必须用 $elemMatch

db.products.find({ attributes: { $elemMatch: { color: "black", size: "XL" } } })

🔹 4. 混合数组/对象规则

示例数据

{ "name": "Book", "tags": ["小说", "科幻", "战争"], "publisher": { "name": "三联出版社", "address": { "city": "北京", "zip": "100000" } } }

索引展开

db.books.createIndex({ "$**": 1 })

展开为:

"tags" -> "小说" "tags" -> "科幻" "tags" -> "战争" "publisher.name" -> "三联出版社" "publisher.address.city" -> "北京" "publisher.address.zip" -> "100000"

✅ 查询:

db.books.find({ tags: "科幻" }) db.books.find({ "publisher.address.city": "北京" })

都会用到通配符索引。


🔹 5. 注意事项

  1. 数组嵌套对象时 → 必须用 $elemMatch 才能保证同一对象条件。

  2. 索引大小 → 如果字段太多(数组过大、对象属性过多),索引体积会膨胀。

  3. 覆盖查询(covered query) → 通配符索引不支持覆盖查询。

  4. 性能 → 通配符索引更灵活,但效率不如手动设计的精准索引。


✅ 总结

  • 对象:通配符索引会递归索引每个子字段。

  • 数组:通配符索引会对数组展开,等价于多键索引。

  • 数组嵌套对象:会索引每个对象的字段,但查询要用 $elemMatch 才能保证在同一个对象里匹配多个条件。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部