createIndexes
在此页面上
定义
createIndexes
为集合构建一个或多个索引。
提示
在
mongosh
中,此命令也运行通过db.collection.createIndex()
和db.collection.createIndexes()
辅助方法运行。辅助方法对
mongosh
用户来说很方便,但它们返回的信息级别可能与数据库命令不同。如果不追求方便或需要额外的返回字段,请使用数据库命令。
兼容性
此命令可用于以下环境中托管的部署:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
注意
所有 MongoDB Atlas 集群都支持此命令。有关所有命令的信息,请参阅不支持的命令。
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
语法
createIndexes
命令采用以下形式:
db.runCommand( { createIndexes: <collection>, indexes: [ { key: { <key-value_pair>, <key-value_pair>, ... }, name: <index_name>, <option1>, <option2>, ... }, { ... }, { ... } ], writeConcern: { <write concern> }, commitQuorum: <int|string>, comment: <any> } )
命令字段
createIndexes
命令采用以下字段:
字段 | 类型 | 说明 |
---|---|---|
createIndexes | 字符串 | 要创建索引的集合。 |
indexes | 阵列 | 指定要创建的索引。数组中的每个文档都指定一个单独的索引。 |
writeConcern | 文档 | 可选。表达写关注的文档。省略以使用默认写关注。 |
commitQuorum | 整数或字符串 | 可选。承载数据的副本集成员的最小数量(即提交法定节点数),包括主节点,必须在主节点将 从 MongoDB v5.0 开始,您可以在 提交法定人数中的副本集节点必须将 支持以下值:
|
comment | any | 可选。用户提供的待附加到该命令的注释。设置后,该注释将与该命令的记录一起出现在以下位置:
注释可以是任何有效的 BSON 类型(字符串、整型、对象、数组等)。 |
indexes
数组中的每个文档都可以采用以下字段:
字段 | 类型 | 说明 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
key | 文档 | |||||||||||
name | 字符串 | 唯一地标识索引的名称。 | ||||||||||
unique | 布尔 | |||||||||||
partialFilterExpression | 文档 | |||||||||||
sparse | 布尔 | |||||||||||
expireAfterSeconds | 整型 | 可选。指定以秒为单位的生存时间 (TTL) 值,以便控制 MongoDB 在此集合中保留文档的时长。此选项仅会应用于 TTL 索引。请参阅通过设置 TTL 使集合中的数据过期以了解更多信息。 如果您使用 MongoDB 5.0 之前版本创建的 TTL 索引,或者要将 MongDB 5.0 创建的数据与之前版本同步,请参阅使用 NaN 配置索引,以避免错误配置问题。 TTL 索引 | ||||||||||
布尔 | 可选。一个标志,用于确定索引是否对查询规划器隐藏。选择查询计划时不会对隐藏索引进行评估。 默认值为 | |||||||||||
storageEngine | 文档 | 可选。允许用户在创建索引时基于每个索引配置存储引擎。
在复制过程中,对创建索引时指定的存储引擎配置选项进行验证并记录到 oplog 中,以支持包含使用不同存储引擎的成员的副本集。 | ||||||||||
weights | 文档 | 可选。对于文本索引,指的是包含字段和权重对的文档。权重是一个从1到99的整数, 999表示该字段在分数方面相对于其他索引字段的重要性。您可以为部分或全部索引字段指定权重。请参阅为自管理部署上的文本搜索结果分配权重以调整分数。默认值为 1 。 | ||||||||||
default_language | 字符串 | 可选。对于文本索引,确定停用词列表的语言以及词干分析器和分词器的规则。有关可用语言,请参阅自管理部署上的文本搜索语言;有关更多信息和示例,请参阅为自管理部署上的文本索引指定默认语言。默认值为 | ||||||||||
language_override | 字符串 | |||||||||||
textIndexVersion | 整型 | 可选。 有关可用版本,请参阅自管理部署上的文本索引版本。 | ||||||||||
2dsphereIndexVersion | 整型 | 可选。 有关可用版本,请参阅 2dsphere 索引。 | ||||||||||
bits | 整型 | |||||||||||
min | 数字 | 可选。对于 2d 索引,这是经度和纬度值的包含下边界。默认值为 -180.0 。 | ||||||||||
max | 数字 | 可选。对于 2d 索引,这是经度和纬度值的包含上边界。默认值为 180.0 。 | ||||||||||
collation | 文档 | 可选。指定索引的排序规则。 排序规则允许用户为字符串比较指定特定于语言的规则,例如字母大小写和重音符号规则。 如果在集合级别指定排序规则:
排序规则选项的语法如下:
指定排序规则时, | ||||||||||
wildcardProjection | 文档 | 可选。 允许用户使用
默认情况下,通配符索引会省略
|
mongosh
提供方法 db.collection.createIndex()
和 db.collection.createIndexes()
作为 createIndexes
命令的封装器。
Considerations
MongoDB 不允许创建版本 0 索引。
索引名称
如果您使用一个名称创建索引,然后尝试使用另一个名称再次创建相同的索引,则 createIndexes
命令和 mongosh
辅助命令 db.collection.createIndex()
和 db.collection.createIndexes()
会报告错误。
{ "ok" : 0, "errmsg" : "Index with name: x_1 already exists with a different name", "code" : 85, "codeName" : "IndexOptionsConflict" }
在以前的版本中,MongoDB 不会再次创建索引,但会返回 ok
值为 1
的响应对象以及暗示未重新创建索引的注释。例如:
{ "numIndexesBefore" : 2, "numIndexesAfter" : 2, "note" : "all indexes already exist", "ok" : 1 }
副本集和分片集群
注意
需要 featureCompatibilityVersion 4.4+
副本集或分片集群中的每个 mongod
必须将 featureCompatibilityVersion 设置为至少 4.4
,才能跨副本集节点同时启动索引构建。
索引构建在副本集或分片集群上,并在所有数据承载副本集成员上同时构建。对于分片集群,索引构建仅会在包含当前被索引集合的数据的分片上进行。主节点需要最少数量的数据承载 voting
节点(即提交法定节点数),包括其自身,这些节点必须在将索引标记为可供使用之前完成构建。 有关详细信息,请参阅复制环境中的索引构建。
要使用非默认提交法定人数启动索引构建,请指定 commitQuorum。
使用 setIndexCommitQuorum
命令修改正在进行的索引构建的提交法定节点数。
为了最大限度地减少构建索引对副本集和分片集群的影响,请使用滚动索引构建过程,如在副本集上构建滚动索引中所述。
排序规则和索引类型
以下索引只支持简单的二进制比较,不支持排序规则:
提示
要在具有非简单排序规则的集合上创建 text
或 2d
索引,您必须在创建索引时显式指定 {collation:
{locale: "simple"} }
。
Stable API
使用 Stable API V1 时:
您不能在
indexes
数组中指定以下任何字段:background
bucketSize
sparse
storageEngine
无法创建 geoHaystack 或文本索引。
在 严格模式 , 查询规划 器会忽略上述不支持的索引类型。示例,尝试将
sparse
索引与cursor.hint()
一起使用将导致以下BadValue
错误:planner returned error :: caused by :: hint provided does not correspond to an existing index
行为
并发
对于 featureCompatibilityVersion "4.2"
,createIndexes
使用优化的构建进程,该进程在索引构建开始和结束时获取并保持对指定集合的独占锁。对集合的所有后续操作都必须等到 createIndexes
释放独占锁后进行。createIndexes
支持在索引构建的大部分时间交叉进行读写操作。
对于 featureCompatibilityVersion "4.0"
,createIndexes
会使用 4.2 之前的索引构建流程,默认情况下会获得在整个构建流程中持续应用于父数据库的独占锁。4.2 之前的构建流程会阻塞对数据库以及其所有集合的所有操作,直到该操作完成。background
索引不会采用独占锁。
有关 createIndexes
的锁定行为的更多信息,请参阅在填充集合上构建索引。
重要
如果无法访问承载数据的投票节点,并且将commitQuorum设立为默认votingMembers
,则索引构建可能会挂起,直到该节点重新在线。
内存使用限制
createIndexes
支持在集合上建立一个或多个索引。createIndexes
使用磁盘上的内存和临时文件的组合来完成索引构建。createIndexes
的内存使用量的默认限制为 200 MB,在使用单个 createIndexes
命令生成的所有索引之间共享。达到内存限制后,createIndexes
将使用 --dbpath
目录中名为 _tmp
的子目录中的临时磁盘文件来完成构建。
您可以通过设置 maxIndexBuildMemoryUsageMegabytes
服务器参数来覆盖内存限制。设置更高的内存限制可能会加快完成索引构建过程。但是,相对于系统上未使用的 RAM 而言,将此限制设置得太高可能会导致内存耗尽和服务器关闭。
索引选项
Non-Hidden Option
更改索引选项
可以更新现有索引的排序规则选项。要更改其他索引选项,请先通过 db.collection.dropIndex()
删除现有索引,然后使用新选项运行 createIndexes
。
排序规则选项
您可以使用不同的排序规则对同一键创建多个索引。 要创建具有相同键模式但不同排序规则的索引,您必须提供唯一索引名称。
如果在集合级别指定排序规则:
如果创建索引时未指定排序规则,MongoDB 将使用集合的默认排序规则创建索引。
如果您在创建索引时指定了排序规则,MongoDB 将使用指定的排序规则创建索引。
提示
通过指定排序规则 strength
为 1
或 2
,您可以创建不区分大小写的索引。排序规则 strength
为 1
的索引既不区分变音符号,也不区分大小写。
要使用索引进行字符串比较,操作还必须指定相同的排序规则。换言之,如果一个操作对索引字段进行字符串比较,但又设定了与索引字段不同的排序规则,那么这个设有排序规则的索引将无法支持该操作。
警告
由于配置了排序规则的索引是通过 ICU 排序规则键来实现排序,因此,相比未配置排序规则的索引的索引键,有排序规则感知的索引键可能会更大。
例如,集合 myColl
在字符串字段 category
上具有一个索引,排序规则语言环境为 "fr"
。
db.myColl.createIndex( { category: 1 }, { collation: { locale: "fr" } } )
以下查询操作指定了与索引相同的排序规则,因此可以使用索引:
db.myColl.find( { category: "cafe" } ).collation( { locale: "fr" } )
而以下查询操作默认使用“简易的”二进制排序器,因此无法使用索引:
db.myColl.find( { category: "cafe" } )
如果一个复合索引的前缀键不是字符串、数组和嵌入式文档,在这种情况下,即使查询操作指定了一个与索引不同的排序规则,它仍然可以利用该复合索引来支持对其前缀健的比较。
例如,集合 myColl
在数值字段 score
和 price
以及字符串字段 category
上有一个复合索引;该索引使用排序规则语言环境 "fr"
创建,用于进行字符串比较:
db.myColl.createIndex( { score: 1, price: 1, category: 1 }, { collation: { locale: "fr" } } )
以下操作使用 "simple"
二进制排序规则进行字符串比较,它们可以使用索引:
db.myColl.find( { score: 5 } ).sort( { price: 1 } ) db.myColl.find( { score: 5, price: { $gt: NumberDecimal( "10" ) } } ).sort( { price: 1 } )
以下操作使用 "simple"
二进制排序规则对索引的 category
字段进行字符串比较,它们可以使用索引仅完成查询的 score: 5
部分:
db.myColl.find( { score: 5, category: "cafe" } )
重要
与文档键(包括嵌入式文档键)的匹配使用简单的二进制比较。这意味着类似“foo.bár”的键的查询不会匹配“foo.bar”键,无论您为 strength 参数设置了什么值。
隐藏选项
要更改现有索引的 hidden
选项,您可以使用以下 mongosh
方法:
例如,
要将索引的
hidden
选项更改为true
,请使用db.collection.hideIndex()
方法:db.restaurants.hideIndex( { borough: 1, ratings: 1 } ); 要将索引的
hidden
选项更改为false
,请使用db.collection.unhideIndex()
方法:db.restaurants.unhideIndex( { borough: 1, city: 1 } );
通配符索引 (Wildcard Indexes)
默认情况下,通配符索引会省略
_id
字段。要将_id
字段包含在通配符索引中,必须将其显式包含在wildcardProjection
文档中:{ "wildcardProjection" : { "_id" : 1, "<field>" : 0|1 } } wildcardProjection
文档中的所有语句必须是包含语句或排除语句中的一种。您还可以在排除语句中包含_id
字段。这是该规则的唯一例外。不支持通配符索引:
通配符索引是稀疏(Sparse)索引。当索引字段不存在时,它们不支持查询。如果通配符字段的值为
null
,则通配符索引将对文档进行索引。从 MongoDB 7.0 开始,通配符索引支持升序 (
1
) 和降序 (-1
) 排序顺序。早期版本仅支持升序。
要了解详情,请参阅:
事务
如果事务不是跨分片写事务,则可以在分布式事务中创建集合和索引。
要在事务中使用 createIndexes
,该事务必须使用读关注 "local"
。如果指定 "local"
以外的读关注级别,则该事务将失败。
提交法人数与写关注的对比
索引构建使用提交法定人数。
写入操作使用写关注。
集群中的每个承载数据的节点均为一个有投票权成员。
提交法定人数指定在主节点 (primary node in the replica set)节点执行提交之前必须准备好多少个承载数据的投票节点或哪些投票节点(包括主节点 (primary node in the replica set)节点)来提交同步索引构建。
写关注是指确认写入操作已传播到指定数量的实例的级别。
版本8.0中的更改:提交法定人数指定在主节点 (primary node in the replica set)节点提交索引构建之前必须准备好多少个节点才能完成索引构建。相反,当主节点 (primary node in the replica set)节点已提交索引构建时,写关注(write concern)指定在命令返回成功之前有多少个节点必须复制索引构建oplog条目。
在以前的版本中,当主节点 (primary node in the replica set)节点提交索引构建时,写关注(write concern)指定在命令返回成功之前必须有多少个节点完成索引构建。
例子
以下命令会在 products
数据库的 inventory
集合上构建两个索引:
db.getSiblingDB("products").runCommand( { createIndexes: "inventory", indexes: [ { key: { item: 1, manufacturer: 1, model: 1 }, name: "item_manufacturer_model", unique: true }, { key: { item: 1, supplier: 1, model: 1 }, name: "item_supplier_model", unique: true } ], writeConcern: { w: "majority" } } )
在索引成功完成构建时,MongoDB 返回一个结果文档,其中包含 "ok" : 1
状态。
创建通配符索引
注意
有关“通配符索引”的完整文档,请参阅“通配符索引”。
下面列出了创建通配符索引的示例:
对单个字段路径(Field Path)创建通配符索引
以某一 products_catalog
集合为例,其中的文档可能包含 product_attributes
字段。product_attributes
字段可包含任意嵌套字段,其中包括嵌入式文档文档和数组:
db.products_catalog.insertMany( [ { _id : ObjectId("5c1d358bf383fbee028aea0b"), product_name: "Blaster Gauntlet", product_attributes: { price: { cost: 299.99, currency: "USD" } } }, { _id: ObjectId("5c1d358bf383fbee028aea0c"), product_name: "Super Suit", product_attributes: { superFlight: true, resistance: [ "Bludgeoning", "Piercing", "Slashing" ] } } ] )
以下操作在 product_attributes
字段上创建一个通配符索引:
use inventory db.runCommand( { createIndexes: "products_catalog", indexes: [ { key: { "product_attributes.$**" : 1 }, name: "wildcardIndex" } ] } )
通过此通配符索引,MongoDB 可以对 product_attributes
的所有标量值建立索引。如果字段是嵌套文档或数组,则通配符索引将递归到文档/数组中,并为文档/数组中的所有标量字段建立索引。
通配符索引可以支持对 product_attributes
或其嵌套字段之一进行任意单字段查询:
db.products_catalog.find( { "product_attributes.superFlight" : true } ) db.products_catalog.find( { "product_attributes.maxSpeed" : { $gt : 20 } } ) db.products_catalog.find( { "product_attributes.elements" : { $eq: "water" } } )
注意
特定于路径的通配符索引语法与 wildcardProjection
选项不兼容。有关更多信息,请参阅参数文档。
对所有字段路径创建通配符索引
以某一 products_catalog
集合为例,其中的文档可能包含 product_attributes
字段。product_attributes
字段可包含任意嵌套字段,其中包括嵌入式文档文档和数组:
db.products_catalog.insertMany( [ { _id : ObjectId("5c1d358bf383fbee028aea0b"), product_name: "Blaster Gauntlet", product_attributes: { price: { cost: 299.99, currency: "USD" } } }, { _id: ObjectId("5c1d358bf383fbee028aea0c"), product_name: "Super Suit", product_attributes: { superFlight: true, resistance: [ "Bludgeoning", "Piercing", "Slashing" ] } } ] )
以下操作对所有标量字段(不包括 _id
字段)创建通配符索引:
use inventory db.runCommand( { createIndexes: "products_catalog", indexes: [ { key: { "$**" : 1 }, name: "wildcardIndex" } ] } )
通过此通配符索引,MongoDB 可为集合中每个文档的所有标量字段建立索引。如果给定字段是嵌套文档或数组,则通配符索引将递归到文档/数组中并对文档/数组中的所有标量字段构建索引。
创建的索引可以支持对集合中文档内任意字段的查询:
db.products_catalog.find( { "product_price" : { $lt : 25 } } ) db.products_catalog.find( { "product_attributes.elements" : { $eq: "water" } } )
注意
默认情况下,通配符索引会省略 _id
字段。要将 _id
字段包含在通配符索引中,则必须将其明确包含在wildcardProjection
文档中。查看参数文档以获取更多信息。
在多个特定字段路径上创建通配符索引
以某一 products_catalog
集合为例,其中的文档可能包含 product_attributes
字段。product_attributes
字段可包含任意嵌套字段,其中包括嵌入式文档文档和数组:
db.products_catalog.insertMany( [ { _id : ObjectId("5c1d358bf383fbee028aea0b"), product_name: "Blaster Gauntlet", product_attributes: { price: { cost: 299.99, currency: "USD" } } }, { _id: ObjectId("5c1d358bf383fbee028aea0c"), product_name: "Super Suit", product_attributes: { superFlight: true, resistance: [ "Bludgeoning", "Piercing", "Slashing" ] } } ] )
以下操作创建通配符索引并使用wildcardProjection
选项,以仅在索引中包含product_attributes.elements
和product_attributes.resistance
字段的标量值。
use inventory db.runCommand( { createIndexes: "products_catalog", indexes: [ { key: { "$**" : 1 }, "wildcardProjection" : { "product_attributes.elements" : 1, "product_attributes.resistance" : 1 }, name: "wildcardIndex" } ] } )
虽然键模式 "$**"
涵盖了文档中的所有字段,但 wildcardProjection
字段将索引限制为只有所包含的字段及其嵌套字段。
如果字段是嵌套文档或数组,则通配符索引将递归到文档/数组中并对文档/数组中的所有标量字段构建索引。
创建的索引可支持对 wildcardProjection
中包含的任何标量字段查询:
db.products_catalog.find( { "product_attributes.elements" : { $eq: "Water" } } ) db.products_catalog.find( { "product_attributes.resistance" : "Bludgeoning" } )
注意
通配符索引不支持在 wildcardProjection
文档中混用包含和排除语句,除非显示包含 _id
字段时。有关 wildcardProjection
的更多信息,请参阅参数文档。
创建排除多个特定字段路径的通配符索引
以某一 products_catalog
集合为例,其中的文档可能包含 product_attributes
字段。product_attributes
字段可包含任意嵌套字段,其中包括嵌入式文档文档和数组:
db.products_catalog.insertMany( [ { _id : ObjectId("5c1d358bf383fbee028aea0b"), product_name: "Blaster Gauntlet", product_attributes: { price: { cost: 299.99, currency: "USD" } } }, { _id: ObjectId("5c1d358bf383fbee028aea0c"), product_name: "Super Suit", product_attributes: { superFlight: true, resistance: [ "Bludgeoning", "Piercing", "Slashing" ] } } ] )
以下操作可创建通配符索引,并使用 wildcardProjection
文档对集合中每个文档的所有标量字段进行索引,不包括 product_attributes.elements
和 product_attributes.resistance
字段:
use inventory db.runCommand( { createIndexes: "products_catalog", indexes: [ { key: { "$**" : 1 }, "wildcardProjection" : { "product_attributes.elements" : 0, "product_attributes.resistance" : 0 }, name: "wildcardIndex" } ] } )
键模式"$**"
涵盖文档中的所有字段,而wildcardProjection
字段则从索引中排除指定字段。
如果字段是嵌套文档或数组,则通配符索引将递归到文档/数组中并对文档/数组中的所有标量字段构建索引。
创建的索引可以支持对任何标量字段的查询,但 wildcardProjection
排除的字段除外:
db.products_catalog.find( { "product_attributes.maxSpeed" : { $gt: 25 } } ) db.products_catalog.find( { "product_attributes.superStrength" : true } )
注意
通配符索引不支持在 wildcardProjection
文档中混用包含和排除语句,除非显示包含 _id
字段时。有关 wildcardProjection
的更多信息,请参阅参数文档。
使用提交法定人数创建索引
注意
需要 featureCompatibilityVersion 4.4+
副本集或分片集群中的每个 mongod
必须将 featureCompatibilityVersion 设置为至少 4.4
,才能跨副本集节点同时启动索引构建。
索引构建在副本集或分片集群上,并在所有数据承载副本集成员上同时构建。对于分片集群,索引构建仅会在包含当前被索引集合的数据的分片上进行。主节点需要最少数量的数据承载 voting
节点(即提交法定节点数),包括其自身,这些节点必须在将索引标记为可供使用之前完成构建。 有关详细信息,请参阅复制环境中的索引构建。
要设置提交法定人数,请使用 createIndexes
来指定 commitQuorum
值。
commitQuorum
指定在主成员执行提交之前必须准备好多少个承载数据的投票成员或哪些投票成员(包括主节点)来提交索引构建。默认提交法定人数为 votingMembers
,这意味着是所有承载数据的成员。
以下操作创建了提交法定人数为 "majority"
的索引,或简单多数的数据承载投票成员:
db.getSiblingDB("examples").runCommand( { createIndexes: "invoices", indexes: [ { key: { "invoices" : 1 }, "name" : "invoiceIndex" } ], "commitQuorum" : "majority" } )
仅在简单多数承载数据的投票成员“投票”提交索引构建后,主节点才会将索引构建标记为准备就绪。有关索引构建和投票过程的更多信息,请参阅复制环境中的索引构建。
输出
createIndexes
命令会返回一个文档,表示操作成功。该文档包含以下部分(但并非全部)字段,具体取决于结果: