点击下方公众号关注并分享获取 MongoDB 最新资讯
通配符索引(Wildcard Indexes):MongoDB 4.2 版本中的新功能。
{ "userMetadata" : { "likes" : [ "dogs", "cats" ] } }
{ "userMetadata" : { "dislikes" : "pickles" } }
{ "userMetadata" : { "age" : 45 } }
{ "userMetadata" : "inactive" }
db.userData.createIndex( { "userMetadata.$**" : 1 } )
db.userData.find({ "userMetadata.likes" : "dogs" })
db.userData.find({ "userMetadata.dislikes" : "pickles" })
db.userData.find({ "userMetadata.age" : { $gt : 30 } })
db.userData.find({ "userMetadata" : "inactive" })
通配符索引(Wildcard indexes)不是用来替代传统索引的。有关创建索引的详细信息,请参阅创建支持查询的索引(Create Indexes to Support Your Queries)。有关通配符索引限制的完整文档,请参见通配符索引限制(Wildcard Index Restrictions)。
创建通配符索引
mongod 的功能兼容性版本(featureCompatibilityVersion)必须是 v4.2 才支撑创建通配符索引。有关设置 fCV 的说明,请参照如何在 MongoDB 6.0 部署中设置特性兼容版本(Set Feature Compatibility Version on MongoDB 6.0 Deployments.)
createIndex数据库命令或它的 mongosh 方法:
createIndex()或
createIndexes()。
在字段上创建通配符索引
为指定字段的值创建索引:
db.collection.createIndex( { "fieldA.$**" : 1 } )
{
"product_name" : "Spy Coat",
"product_attributes" : {
"material" : [ "Tweed", "Wool", "Leather" ]
"size" : {
"length" : 72,
"units" : "inches"
}
}
}
{
"product_name" : "Spy Pen",
"product_attributes" : {
"colors" : [ "Blue", "Black" ],
"secret_feature" : {
"name" : "laser",
"power" : "1000",
"units" : "watts",
}
}
}
db.products_catalog.createIndex( { "product_attributes.$**" : 1 } )
db.products_catalog.find( { "product_attributes.size.length" : { $gt : 60 } } )
db.products_catalog.find( { "product_attributes.material" : "Leather" } )
db.products_catalog.find( { "product_attributes.secret_feature.name" : "laser" } )
特殊路径的通配符索引语法与通配符用法不兼容时,参照 Options for wildcard
indexes 获取更多的帮助。
"$**"作为索引的关键字,对文档中所有字段( _id 除外)的值进行索引:
db.collection.createIndex( { "$**" : 1 } )
默认情况下,通配符索引忽略 _ id字段。要在通配符索引中包含 _ id 字段,必须在通配符投影文档中显式地包含它。更多有关信息,参见通配符索引(wildcard indexes)的选项(Options for wildcard indexes)。
db.collection.createIndex(
{ "$**" : 1 },
{ "wildcardProjection" :
{ "fieldA" : 1, "fieldB.fieldC" : 1 }
}
)
通配符索引不支持在通配符投影文档中混合包含和写排除语句,想对 _ id 字段创建索引,只能显式包含。有关通配符投影(wildcardProjection)的更多信息,参见通配符索引的选项(Options for wildcard indexes)。
db.collection.createIndex(
{ "$**" : 1 },
{ "wildcardProjection" :
{ "fieldA" : 0, "fieldB.fieldC" : 0 }
}
)
通配符索引不支持在通配符投影(wildcardProjection)文档中混合包含和排除语句,除非显式包含 _ id 字段。有关通配符投影(wildcardProjection)的更多信息,参见通配符索引的选项(Options for wildcard indexes)。
注意事项
通配符索引在任何指定的查询条件中最多只能支持一个字段。有关通配符索引查询的更多信息,参见 Wildcard Index Query/Sort Support。
mongd 的功能兼容版本(featureCompatibilityVersion)必须是4.2才能创建通配符索引。有关设置 fCV 的说明,参见 Set Feature Compatibility Version on MongoDB 6.0 Deployments。 默认情况下,通配符索引省略 _id 字段。要在通配符索引中包含 _id 字段,必须在通配符投影文档 wildcardProjection(即{“ _ id”: 1})中显式包含它。
可以在集合(collection)中创建多个通配符索引。
通配符索引可以覆盖与集合(collection)中的其他索引相同的字段。
通配符索引是稀疏索引(Sparse Indexes),只包含具有索引字段的文档的条目,允许索引字段包含空值。
特性
通配符索引在索引对象(即嵌入式文档 embedded document)或数组字段时具有递归遍历的特性:
如果字段是一个对象(object),则通配符索引将递归到该对象的最后一层嵌套,并对其内容进行索引。 如果该字段是一个数组,则通配符索引将遍历该数组并对每个元素进行索引:
如果数组中的某个元素是一个对象,则通配符索引将深入到该对象中,以按照上面所述对其内容进行索引。 如果元素是一个数组——即直接嵌入在父数组中的数组——那么通配符索引不会遍历嵌入的数组,而是将整个数组作为单个值进行索引。 对于所有其他字段,将基础原语 primitive(非对象/数组)的值记录到索引中。
通配符索引持续遍历任何其他嵌套对象或数组,直到达到一个基本值(即不是对象或数组的字段)。然后对这个基本值以及该字段的完整路径进行索引。
例如:
{
"parentField" : {
"nestedField" : "nestedValue",
"nestedObject" : {
"deeplyNestedField" : "deeplyNestedValue"
},
"nestedArray" : [
"nestedArrayElementOne",
[ "nestedArrayElementTwo" ]
]
}
}
"parentField.nestedField" : "nestedValue""parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue"
"parentField.nestedArray" : "nestedArrayElementOne"
"parentField.nestedArray" : ["nestedArrayElementTwo"]
parentField.nestedArray 的记录是无序的。通配符索引在将元素写到索引中时忽略数组元素的位置。通配符索引仍然可以支持含有显式数组索引的查询。参照 Queries with Explicit Array Indices 获取详情。
有关嵌套对象的通配符索引行为的更多信息,请参阅:Nested Objects。
有关嵌套数组的通配符索引行为的详细信息,请参阅:Nested Arrays。
嵌套对象(Nested Objects)
当通配符索引遇到嵌套对象时,它会遍历到对象中并对其内容进行索引。例如:
{
"parentField" : {
"nestedField" : "nestedValue",
"nestedArray" : ["nestedElement"]
"nestedObject" : {
"deeplyNestedField" : "deeplyNestedValue"
}
}
}
字段本身是一个对象(例如一个嵌入式文档) ,下降到该对象以索引其内容。 作为数组的字段,遍历数组并索引其内容。 其他字段,将基本元素(非对象/数组)值记录到索引中。
通配符索引继续遍历任何其他嵌套对象或数组,直到达到一个基本值(即不是对象或数组的字段)。然后对该基元值以及该字段的完整路径进行索引。
给定示例文档,通配符索引将以下记录添加到索引中:
"parentField.nestedField" : "nestedValue""parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue""parentField.nestedArray" : "nestedElement"
有关嵌套数组的通配符索引行为的更多信息,请参阅:Nested Arrays。
嵌套数组(Nested Arrays)
当通配符索引遇到嵌套数组时,它尝试遍历数组以索引其元素。如果数组本身是父数组(即嵌入数组)中的一个元素,则通配符索引将整个数组记录为一个值,而不是遍历其内容。例如:
{
"parentArray" : [
"arrayElementOne",
[ "embeddedArrayElement" ],
"nestedObject" : {
"nestedArray" : [
"nestedArrayElementOne",
"nestedArrayElementTwo"
]
}
]
}
字段本身是一个对象(例如一个嵌入式文档) ,下降到该对象以索引其内容。
作为数组的字段,遍历数组并索引其内容。 其他字段,将基本元素(非对象/数组)值记录到索引中。
"parentArray" : "arrayElementOne""parentArray" : ["embeddedArrayElement"]"parentArray.nestedObject.nestedArray" : "nestedArrayElementOne""parentArray.nestedObject.nestedArray" : "nestedArrayElementTwo"
注意,parentField.nestedArray 的记录不包括每个元素的数组位置。通配符索引在将元素记录到索引中时忽略数组元素的位置。通配符索引仍然可以支持包含显式数组索引的查询。请参阅:Queries with Explicit Array Indices
限制条件
不能使用通配符索引分片集合。在要分片的一个或多个字段上创建非通配符索引。有关选择碎片键的详细信息,请参阅碎片键(Shard Keys)。
不能创建复合索引。 不能为通配符索引指定下列属性:
不能使用通配符语法创建下列索引类型:
⚠️ 重要:
通配符索引与通配符文本索引(Wildcard Text Indexes)不同且不兼容。通配符索引不支持使用 $Text 运算符的查询。
有关通配符索引创建限制的完整文档,参见不兼容索引类型或属性(Incompatible Index Types or Properties)。
通配符索引查询/排序支持
满足查询条件的查询计划,可以利用通配符索引。
查询条件正好命中通配符索引所覆盖的一个字段。
排除了 _ id 字段,只包括查询字段。
指定的查询字段不能是数组。
覆盖查询
db.employees.createIndex( { "$**" : 1 } )
db.employees.find(
{ "lastName" : "Doe" },
{ "_id" : 0, "lastName" : 1 }
)
MongoDB 的查询条件不可以在使用通配符索引时还覆盖其他索引。
MongoDB 的查询条件不可以同时覆盖两个通配符索引。
一个通配符索引可以支持多个字段联合查询,也可以只使用通配符索引包含的其中一个字段查询。
查询条件对应的查询计划命中通配符索引。
只能针对查询条件中的字段 sort () 排序。
排序指定的字段不能是数组。
db.products.createIndex( { "product_attributes.$**" : 1 } )
db.products.find(
{ "product_attributes.price" : { $gt : 10.00 } },
).sort(
{ "product_attributes.price" : 1 }
)
通配符索引不支持使用文档中不存在字段的查询。
通配符索引不支持检查字段是否等于文档或数组的查询条件。
通配符索引不支持检查字段是否为空的查询条件。
{
"parentObject" : {
"nestedArray" : [
"elementOne",
{
"deeplyNestedArray" : [ "elementTwo" ]
}
]
}
}
"parentObject.nestedArray.0" : "elementOne""parentObject.nestedArray.1.deeplyNestedArray.0" : "elementTwo"
如果查询条件中的给定字段路径使用了超过 8 个显式数组索引,MongoDB 不会利用通配符索引来响应该字段路径。
"parentObject.nestedArray" : "elementOne"parentObject.nestedArray.deeplyNestedArray" : "elementTwo"
另见:BSON文档的嵌套深度 Nested Depth for BSON Documents
关于译者:
【推荐阅读】
社区招募
为了让社区组委会成员和志愿者朋友们灵活参与,同时我们为想要深度参与社区建设的伙伴们开设了“招募通道”,如果您想要在社区里面结交志同道合的技术伙伴,想要通过在社区沉淀有价值的干货内容,想要一个展示自己的舞台,提升自身的技术影响力,即刻加入社区贡献队伍~ 点击提交申请 社区合作
接下来我们会在诸多城市举办技术大会,如果您有优质的议题和 MongoDB 相关经验的嘉宾可以与我们分享,或者有赞助合作意向的小伙伴,包含但不限制于联合主办方、媒体合作等,都可以随时联系我们的社区助手小芒果(微信ID:mongoingcom)沟通具体事宜。 重要资讯
感谢大家一直以来对社区的关注与支持!社区在大家共同的努力下不断发展与壮大,为了给大家营造更便捷的交流环境,QQ 技术交流群将同步在“微信技术交流群”中。扫描下方二维码添加小芒果微信发送“mongo”即可进入技术交流群。
获取更多精彩内容点击社区网站www.mongoing.com
扫描上方二维码添加小芒果微信
(ID:mongoingcom)
进入中文用户组技术交流群
长按二维码加入我们






