复合通配符索引
7.0 版本中的新增功能。
MongoDB 支持在一个字段或一组字段上创建通配符索引。 一个复合索引有多个术语。复合通配符索引具有一个通配符术语和一个或多个附加索引术语。
重要
通配符索引不会取代基于工作负载的索引规划。
有关创建支持工作负载的索引的详细信息,请参阅创建索引以支持查询。
用例
使用属性模式搜索
属性模式是搜索具有共同特征的文档的有用技术。
不幸的是,创建大量单独的索引来覆盖所有可能的查询的成本很高。 通配符索引是创建大量单个索引的良好替代方案,因为一个通配符索引可以有效地覆盖许多潜在的查询。
考虑如下模式:
{ tenantId: <Number>, tenantRegion: <Number>, customFields: { addr: <String>, name: <String>, blockId: <Number>, ... } dateOpened: <Date> }
您可能想要查询具有特定tenantId
的租户的 customFields
字段的各个方面。 您可以创建一系列单独的索引:
{ tenantId: 1, "customFields.addr": 1 } { tenantId: 1, "customFields.name": 1 } { tenantId: 1, "customFields.blockId": 1 } ...
这种方法很难维护,而且很可能会达到每个集合的最大索引数 (64)。
请改用复合通配符索引。 复合通配符索引更易于编写和维护,并且不太可能达到 64 个collection的限制。
此示例在salesData
collection 上创建复合通配符索引:
db.runCommand( { createIndexes: "salesData", indexes: [ { key: { tenantId: 1, "customFields.$**": 1 }, name: "tenant_customFields" } ] } )
通配符"customFields.$**"
指定customFields
字段中的所有子字段。 另一个术语tenantId
不是通配符规范;它是标准字段规范。
行为
要创建通配符索引,请使用标准索引创建命令:
通配符索引的一般注意事项
默认情况下,通配符索引会省略
_id
字段。 要将_id
字段包含在通配符索引中,必须将其明确包含在wildcardProjection
文档中。db.salesData.createIndex( { "$**" : 1 }, { "wildcardProjection" : { "_id": 1, "customers.lastName": 1, "customers.FirstName": 1, } } ) 您可以在一个collection上创建多个通配符索引。
通配符索引可能涵盖与collection中其他索引相同的字段。
通配符索引很稀疏。 它们仅包括包含索引字段的文档的条目。
如果复合通配符索引中的所有字段均缺失,则不会对文档编制索引。
复合通配符索引注意事项
复合通配符索引是稀疏索引。
如果文档缺少通配符字段但具有复合字段之一,则该文档将包含在索引中。
索引字段(包括通配符字段)可以按升序 (
1
) 或降序 (-1
) 排序。
开始体验
筛选字段 wildcardProjection
您可以使用wildcardProjection
来指定各个子字段。
db.runCommand( { createIndexes: "salesData", indexes: [ { key: { tenantId: 1, "$**": 1 }, name: "tenant_customFields_projection", wildcardProjection: { "customFields.addr": 1, "customFields.name": 1 } } ] } )
通配符索引术语"$**"
指定collection中的每个字段。wildcardProjection
将索引限制为指定字段"customFields.addr"
和"customFields.name"
。
wildcardProjection
仅当通配符为$**
时,才能使用 。
使用辅助方法创建通配符索引
MongoDB 为大多数 数据库命令 提供了 Shell 助手方法 。这些 shell 方法提供简化的语法,并且在功能上等同于数据库命令。
第一个示例的 shell 助手是:
db.salesData.createIndex( { tenantId: 1, "customFields.$**": 1 }, { name: "tenant_customFields_shellHelper" } )
第二个示例的 Shell 助手是:
db.salesData.createIndex( { tenantId: 1, "$**": 1 }, { "wildcardProjection": { "customFields.addr": 1, "customFields.name": 1 }, name: "tenant_customFields_projection_helper" } )
如果要比较 Shell 命令和数据库命令,必须删除命令调用之间的索引。 即使使用不同的名称,也不能两次创建相同的索引。
要删除索引,请插入索引名称并运行db.collection.dropIndex()。
db.salesData.dropIndex( "tenant_customFields" )
前面的命令会从salesData
数据库中删除"tenant_customFields"
索引。
创建部分复合通配符索引
如需创建部分复合通配符索引,可以使用partialFilterExpression
选项指定过滤表达式,使索引仅包含符合过滤条件的文档。partialFilterExpression
可以覆盖索引中包含或未包含的字段。
以下示例仅针对 tenantRegion
为 1
的文档,对 tenantId
字段和 customFields
字段中的所有子字段创建部分复合通配符索引。
db.runCommand( { createIndexes: "salesData", indexes: [ { key: { tenantId: 1, "customFields.$**": 1 }, name: "tenant_customFields_partial", partialFilterExpression: { tenantRegion: 1 } } ] } )