创建索引
在本页
定义
createIndexes在集合上构建一个或多个索引。
提示
在
mongosh中,此命令也可以通过db.collection.createIndex()和db.collection.createIndexes()辅助方法来运行。.辅助方法对于
mongosh用户来说很方便,但它们可能不会返回与数据库命令相同级别的信息。在不需要便利性或需要额外的返回字段的情况下,请使用数据库命令。
兼容性
此命令在以下环境中托管的部署中可用
MongoDB Atlas:云中MongoDB部署的全托管服务
注意
此命令支持所有MongoDB Atlas集群。有关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 需要以下字段
字段 | 类型 | 描述 |
|---|---|---|
创建索引 | string | 要为其创建索引的集合。 |
indexes | array | 指定要创建的索引。数组中的每个文档指定一个单独的索引。 |
writeConcern | document | 可选。表示写关注的文档。省略则使用默认写关注。 |
commitQuorum | 整数或字符串 | 可选。在主节点将索引标记为就绪之前,必须报告成功索引构建的数据承载副本集成员(即提交法定人数)的最小数量,包括主节点。 从MongoDB v5.0开始,当提交法定人数设置为 提交法定人数中的副本集节点必须将 支持以下值
|
注释 | 任何 | 可选。为该命令提供的注释。一旦设置,此注释将出现在以下位置的该命令记录旁边:
注释可以是任何有效的BSON类型(字符串、整数、对象、数组等)。 |
indexes数组中的每个文档可以包含以下字段:
字段 | 类型 | 描述 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
key | document | |||||||||||
name | string | 唯一标识索引的名称。 | ||||||||||
unique | 布尔值 | |||||||||||
partialFilterExpression | document | |||||||||||
稀疏 | 布尔值 | |||||||||||
expireAfterSeconds | 整数 | 可选。指定一个以秒为单位的值,作为生存时间(TTL),以控制MongoDB保留此集合中文档的时间。此选项仅适用于TTL索引。有关更多信息,请参阅通过设置TTL从集合中删除数据。 如果您使用的是MongoDB 5.0之前的TTL索引,或者您想将MongoDB 5.0中创建的数据与5.0之前的安装同步,请参阅使用NaN配置的索引以避免配置错误。 TTL索引的 | ||||||||||
布尔值 | 可选。一个标志,用于确定索引是否从查询计划器隐藏。隐藏的索引不是查询计划选择的一部分。 默认值为 | |||||||||||
storageEngine | document | 可选。允许用户在创建索引时为每个索引配置存储引擎。
创建索引时指定的存储引擎配置选项将在复制过程中验证并记录到oplog,以支持使用不同存储引擎的副本集成员。 | ||||||||||
weights | document | 可选。对于文本索引,包含字段和权重对的文档。权重是一个介于1到99,999之间的整数,表示字段相对于其他索引字段的相对重要性,从分数角度考虑。您可以指定一些或所有索引字段的权重。请参阅在自托管部署上分配文本搜索结果的权重以调整分数。默认值为 1。 | ||||||||||
default_language | string | 可选。对于文本索引,确定停用词列表以及词干提取器和分词器规则的语言。请参阅自托管部署上的文本搜索语言以获取可用的语言和自托管部署上文本索引的默认语言以获取更多信息及示例。默认值为 | ||||||||||
language_override | string | |||||||||||
textIndexVersion | 整数 | 可选。《text》索引版本号。用户可以使用此选项来覆盖默认版本号。 有关可用版本,请参阅自托管部署上的文本索引版本。 | ||||||||||
2dsphereIndexVersion | 整数 | 可选。《2dsphere》索引版本号。用户可以使用此选项来覆盖默认版本号。 有关可用版本,请参阅2dsphere索引。 | ||||||||||
bits | 整数 | |||||||||||
min | 数字 | 可选。对于2d索引,经度和纬度值的下限(包含)。默认值为 -180.0。 | ||||||||||
max | 数字 | 可选。对于2d索引,经度和纬度值的上限(包含)。默认值为 180.0。 | ||||||||||
collation | document | 可选。指定索引的排序规则。 排序规则允许用户指定字符串比较的语言特定规则,例如大小写和重音符号的规则。 如果已在集合级别指定了排序规则,那么
排序规则选项具有以下语法 在指定排序时, | ||||||||||
wildcardProjection | document | 可选。 允许用户使用
通配索引默认省略
|
mongosh 提供了db.collection.createIndex()和db.collection.createIndexes()方法作为createIndexes命令的包装器。
注意事项
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 }
副本集和分片集群
副本集或分片集群上的索引构建会在所有承载数据的副本集成员上同时进行。对于分片集群,索引构建只发生在包含要索引的集合数据的分片上。主节点需要最小数量的承载数据的 投票 成员(即提交仲裁),包括自身,在标记索引为可用之前,必须完成构建。有关更多信息,请参阅复制环境中的索引构建。
要使用非默认的提交仲裁启动索引构建,请指定 commitQuorum.
使用 setIndexCommitQuorum 命令修改正在进行中的索引构建的提交仲裁。
为了最小化在副本集和分片集群上创建索引的影响,请使用文档中描述的滚动索引构建过程,详情请参考副本集上的滚动索引构建。
排序规则和索引类型
以下索引仅支持简单的二进制比较,不支持排序规则:
提示
要在具有非简单排序规则的集合上创建text或2d索引,您必须在创建索引时明确指定{collation: {locale: "simple"} }。
稳定API
当使用稳定API V1时
您不能在
indexes数组中指定以下任何字段:backgroundbucketSize稀疏storageEngine
您不能创建geoHaystack或text索引。
上述不支持的索引类型在严格模式下的查询计划中被忽略。例如,尝试使用带有
cursor.hint()的sparse索引会导致以下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 之前的构建过程会阻止数据库及其所有集合上的所有操作,直到操作完成。后台索引不会获取独占锁。
有关 createIndexes 的锁定行为的更多信息,请参阅 已填充集合上的索引构建。
重要
如果承载数据的投票节点变得不可访问,并且 commitQuorum 设置为默认的 votingMembers,则索引构建可能会挂起,直到该节点重新上线。
内存使用限制
createIndexes 支持在集合上构建一个或多个索引。 createIndexes 结合使用内存和磁盘上的临时文件来完成索引构建。默认情况下,createIndexes 的内存使用限制为200兆字节,由使用单个 createIndexes 命令构建的所有索引共享。一旦达到内存限制,createIndexes 将使用位于 --dbpath 目录下名为 _tmp 的子目录中的临时磁盘文件来完成构建。
您可以通过设置 maxIndexBuildMemoryUsageMegabytes 服务器参数来覆盖内存限制。设置更高的内存限制可能会导致索引构建更快完成。然而,如果将此限制设置得太高,相对于系统未使用的RAM,可能会导致内存耗尽和服务器关闭。
索引选项
非隐藏选项
可以更改隐藏选项而不需要删除和重新创建索引。请参阅隐藏选项。
更改索引选项
可以更新现有索引上的排序选项。要更改其他索引选项,请使用 db.collection.dropIndex() 删除现有索引,然后使用新的选项运行 createIndexes。
排序选项
可以在相同的键上创建多个具有不同排序的索引。要创建具有相同键模式但不同排序的索引,必须提供唯一的索引名称。
如果已在集合级别指定了排序规则,那么
如果创建索引时没有指定排序规则,MongoDB将使用集合的默认排序规则创建索引。
如果创建索引时指定了排序规则,MongoDB将使用指定的排序规则创建索引。
提示
通过指定一个 collation(排序规则) 强度为 1 或 2,您可以创建一个不区分大小写的索引。具有 collation(排序规则) 强度为 1 的索引既不区分重音符号也不区分大小写。
为了使用索引进行字符串比较,操作也必须指定相同的排序规则。也就是说,如果操作指定了不同的排序规则,则带有排序规则的索引无法支持在索引字段上执行字符串比较的操作。
警告
由于配置了排序规则的索引使用 ICU 排序规则键来实现排序顺序,因此具有排序规则的索引键可能比未配置排序规则的索引键更大。
例如,集合 myColl 在字符串字段 category 上有一个索引,其排序规则区域设置为 "fr"。
db.myColl.createIndex( { category: 1 }, { collation: { locale: "fr" } } )
以下查询操作,指定了与索引相同的排序规则,可以使用该索引
db.myColl.find( { category: "cafe" } ).collation( { locale: "fr" } )
然而,以下查询操作,默认使用 "simple" 二进制排序规则,不能使用该索引
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" 这样的键匹配,无论您设置的 强度 参数的值如何。
隐藏选项
要更改现有索引的 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 } );
通配符索引
通配索引默认省略
_id字段。要将_id字段包含在通配索引中,您必须在wildcardProjection文档中显式包含它。{ "wildcardProjection" : { "_id" : 1, "<field>" : 0|1 } } wildcardProjection文档中的所有语句都必须是包含或排除语句。您还可以使用排除语句包含_id字段。这是唯一的例外。通配符索引不支持
通配符索引是 稀疏索引。当索引字段不存在时,它们不支持查询。如果通配符字段有一个
null值,则通配符索引将索引文档。从 MongoDB 7.0 开始,通配符索引支持升序(
1)和降序(-1)排序顺序。早期版本仅支持升序。
了解更多信息,请参阅
事务
如果事务不是跨分片写事务,则可以在 分布式事务 内创建集合和索引。不是 跨分片写事务。
要在事务中使用 createIndexes,事务必须使用读取关注点 "local"。如果您指定了除 "local" 之外的读取关注点级别,则事务将失败。
提交投票与写入关注点的对比
提交投票和写入关注点之间存在重要差异:
索引构建使用提交投票。
写操作使用写入关注点。
集群中每个承载数据的节点都是一个投票成员。
提交投票指定在主节点执行提交之前,需要多少个承载数据的投票成员,或者哪些投票成员(包括主节点)必须准备好提交一个 同时索引构建。
写入关注点是指写入传播到指定数量的实例的确认级别。
已更改在版本中8.0: 提交投票指定在主节点提交索引构建之前,需要多少个节点准备好完成索引构建。相比之下,当主节点提交索引构建时,写入关注点指定在命令返回成功之前,需要多少个节点复制索引构建的oplog条目。
在之前的版本中,当主节点提交索引构建时,写入关注点指定在命令返回成功之前,需要多少个节点完成索引构建。
示例
以下命令在 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 的结果文档。
创建通配符索引
注意
关于通配符索引的完整文档,请参阅通配符索引。
以下列出了一些通配符索引创建的示例
在单个字段路径上创建通配符索引
考虑一个集合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 的更多信息,请参阅参数文档。
使用提交法定人数创建索引
副本集或分片集群上的索引构建会在所有承载数据的副本集成员上同时进行。对于分片集群,索引构建只发生在包含要索引的集合数据的分片上。主节点需要最小数量的承载数据的 投票 成员(即提交仲裁),包括自身,在标记索引为可用之前,必须完成构建。有关更多信息,请参阅复制环境中的索引构建。
要设置 提交法定人数,请使用 createIndexes 来指定 commitQuorum 值。
commitQuorum 指定了多少数据承载的投票成员,或者哪些投票成员(包括主节点),必须在主节点执行提交之前准备好提交索引构建。默认的提交法定人数是 votingMembers,这意味着所有数据承载的成员。
以下操作创建了一个具有 "majority" 提交法定人数的索引,即数据承载成员的简单多数。
db.getSiblingDB("examples").runCommand( { createIndexes: "invoices", indexes: [ { key: { "invoices" : 1 }, "name" : "invoiceIndex" } ], "commitQuorum" : "majority" } )
只有当数据承载投票成员中的简单多数“投票”提交索引构建后,才将索引构建标记为就绪。有关索引构建和投票过程的信息,请参阅“primary”,以及“复制环境中的索引构建”。
输出
createIndexes命令返回一个文档,指示操作是否成功。该文档包含以下字段的一些,但不是全部,取决于结果