Docs 菜单

索引

在本指南中,您可以学习如何在 MongoDB Go 驱动程序中使用索引

MongoDB 中的索引支持高效执行查询。如果没有索引,MongoDB 会扫描集合中的每个文档(集合扫描),从而找到与您的查询相匹配的文档。集合扫描很慢,可能会对应用程序的性能产生负面影响。通过适当的索引,MongoDB 可以限制其检查的文档数量。

提示

您还可以在更新操作、删除操作和某些聚合管道阶段中使用索引。

MongoDB 中的查询可以包含以下元素:

元素
必要性
用途

查询

必需

指定您要查找的字段和值。

选项

Optional

指定查询的执行方式。

投射

Optional

指定 MongoDB 返回的字段。

Sort

Optional

指定 MongoDB 返回文档的顺序。

在同一索引中指定这些元素时,MongoDB 会直接从索引返回结果,这也称为覆盖查询

重要

排序条件

您的排序条件必须与索引的顺序一致或相反。

举例来说,以下索引指定字段 name 按升序 (AZ) 排序而 {2} 按降序 (9-0) 排序:

name_1_age_-1

当您按以下任一方式对数据进行排序时,MongoDB 会使用此索引:

  • name 升序, age 降序

  • name 降序,age 升序

指定 nameage 升序或 nameage 降序排序需要进行内存中排序。

如要了解如何确保索引涵盖查询标准和投影,请参阅查询覆盖

若要提高查询性能,请对查询中经常出现的字段和返回排序结果的操作创建索引。追踪索引内存和磁盘使用情况以进行容量规划,因为您添加的每个索引都会消耗磁盘空间和内存。此外,当写入操作更新索引字段时,MongoDB 还必须更新相关索引。

由于 MongoDB 支持动态模式,因此您的应用程序可以查询未知名称或任意名称的字段。MongoDB 4.2 引入了通配符索引,以帮助支持这些查询。通配符索引并不是为了取代基于工作负载的索引规划而设计的。

要进一步了解如何设计数据模型和选择适合应用程序的索引,请参阅索引策略数据建模与索引

MongoDB 支持多种索引类型来支持数据查询。以下各部分描述和演示了如何创建最常见的索引类型。要查看索引类型的完整列表,请参阅索引

单字段索引包含对集合文档中字段的引用。

该索引提高了单字段查询和排序性能,并支持 TTL 索引,可在一定时间后从集合中自动删除文档。

注意

_id_ 索引是单字段索引的一个例子。当您创建新集合时,会在 _id 字段上自动创建此索引。

以下示例在 sample_mflix.movies 集合中的 title 字段上按升序创建索引:

coll := client.Database("sample_mflix").Collection("movies")
indexModel := mongo.IndexModel{
Keys: bson.D{{"title", 1}},
}
name, err := coll.Indexes().CreateOne(context.TODO(), indexModel)
if err != nil {
panic(err)
}
fmt.Println("Name of Index Created: " + name)
Name of Index Created: title_1

复合索引包含对集合文档中多个字段的引用。此索引可提高查询和排序性能。

以下示例在 sample_mflix.movies 集合中的 fullplottitle 字段上创建了复合索引:

coll := client.Database("sample_mflix").Collection("movies")
indexModel := mongo.IndexModel{
Keys: bson.D{
{"fullplot", -1},
{"title", 1}
}
}
name, err := coll.Indexes().CreateOne(context.TODO(), indexModel)
if err != nil {
panic(err)
}
fmt.Println("Name of Index Created: " + name)
Name of Index Created: fullplot_-1_title_1

多键索引使用与单字段索引复合索引相同的语法。该索引提高了将数组字段指定为索引的查询的性能。

以下示例在 sample_mflix.movies 集合中的 cast 字段上创建了一个多键索引:

coll := client.Database("sample_mflix").Collection("movies")
indexModel := mongo.IndexModel{
Keys: bson.D{{"cast", -1}}
}
name, err := coll.Indexes().CreateOne(context.TODO(), indexModel)
if err != nil {
panic(err)
}
fmt.Println("Name of Index Created: " + name)
Name of Index Created: cast_-1

您可以使用Go驾驶员以编程方式管理Atlas Search和Atlas Vector Search索引。

Atlas Search功能使您能够对MongoDB Atlas上托管的集合执行全文搜索。要学习;了解有关Atlas Search 的更多信息,请参阅Atlas Search文档。

Atlas Vector Search使您能够对Atlas中存储的向量嵌入执行语义搜索。要学习;了解有关Atlas Vector Search 的更多信息,请参阅Atlas Vector Search文档。

要学习;了解有关如何运行Atlas Vector Search查询的更多信息,请参阅运行Atlas Vector Search查询指南。

以下部分包含演示如何管理Atlas Search和Atlas Vector Search索引的代码示例。

您可以通过向 SearchIndexView.CreateOne() 方法提供索引定义来创建Atlas Search或Atlas Vector Search索引。

以下示例在 sample_mflix.movies集合的 plot字段上创建Atlas Search索引:

// Sets the index name and type to "search"
const indexName = "search_index"
opts := options.SearchIndexes().SetName(indexName).SetType("search")
// Defines the index definition
searchIndexModel := mongo.SearchIndexModel{
Definition: bson.D{
{Key: "mappings", Value: bson.D{
{Key: "dynamic", Value: false},
{Key: "fields", Value: bson.D{
{Key: "plot", Value: bson.D{
{Key: "type", Value: "string"},
}},
}},
}},
},
Options: opts,
}
// Creates the index
searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
if err != nil {
log.Fatalf("Failed to create the Atlas Search index: %v", err)
}

以下示例在 sample_mflix.embedded_movies集合中的 plot_embedding字段上创建Atlas Vector Search索引:

// Defines the structs used for the index definition
type vectorDefinitionField struct {
Type string `bson:"type"`
Path string `bson:"path"`
NumDimensions int `bson:"numDimensions"`
Similarity string `bson:"similarity"`
Quantization string `bson:"quantization"`
}
type vectorDefinition struct {
Fields []vectorDefinitionField `bson:"fields"`
}
// Sets the index name and type to "vectorSearch"
const indexName = "vector_search_index"
opts := options.SearchIndexes().SetName(indexName).SetType("vectorSearch")
// Defines the index definition
vectorSearchIndexModel := mongo.SearchIndexModel{
Definition: vectorDefinition{
Fields: []vectorDefinitionField{{
Type: "vector",
Path: "plot_embedding",
NumDimensions: 1536,
Similarity: "dotProduct",
Quantization: "scalar"}},
},
Options: opts,
}
// Creates the index
searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, vectorSearchIndexModel)
if err != nil {
log.Fatalf("Failed to create the Atlas Vector Search index: %v", err)
}

您可以使用 SearchIndexView.List() 方法,通过指定索引名称来列出Atlas Search或Atlas Vector Search索引。

以下示例列出了指定Atlas Search或Atlas Vector Search索引的详细信息:

// Specifies the index to retrieve
const indexName = "myIndex"
opts := options.SearchIndexes().SetName(indexName)
// Retrieves the details of the specified index
cursor, err := coll.SearchIndexes().List(ctx, opts)
// Prints the index details to the console as JSON
var results []bson.D
if err := cursor.All(ctx, &results); err != nil {
log.Fatalf("Failed to unmarshal results to bson: %v", err)
}
res, err := json.Marshal(results)
if err != nil {
log.Fatalf("Failed to marshal results to json: %v", err)
}
fmt.Println(res)

您可以使用 SearchIndexView.UpdateOne() 方法,通过指定索引名称和新的索引定义来更新Atlas Search或Atlas Vector Search索引。

以下示例通过提供索引名称和新的索引定义来更新Atlas Vector Search索引:

// Specifies the index name and the new index definition
const indexName = "vector_search_index"
type vectorDefinitionField struct {
Type string `bson:"type"`
Path string `bson:"path"`
NumDimensions int `bson:"numDimensions"`
Similarity string `bson:"similarity"`
}
type vectorDefinition struct {
Fields []vectorDefinitionField `bson:"fields"`
}
definition := vectorDefinition{
Fields: []vectorDefinitionField{
{
Type: "vector",
Path: "plot_embedding",
NumDimensions: 1536,
Similarity: "cosine",
Quantization: "scalar",
},
},
}
// Updates the specified index
err := coll.SearchIndexes().UpdateOne(ctx, indexName, definition)
if err != nil {
log.Fatalf("Failed to update the index: %v", err)
}

您可以使用 SearchIndexView.DropOne() 方法,通过指定索引名称来删除Atlas Search或Atlas Vector Search索引。

以下示例删除具有指定名称的Atlas Search或Atlas Vector Search索引:

// Deletes the specified index
err := coll.SearchIndexes().DropOne(ctx, "myIndex")
if err != nil {
log.Fatalf("Failed to delete the index: %v", err)
}

聚集索引可提高对集群化集合的插入、更新和删除操作的性能。集群化集合可以按聚集索引键值的顺序来存储文档。

要创建聚集索引,请在创建集合时指定聚集索引选项,其中_id字段指定为键,唯一字段为true

以下示例对 db.tea 集合中的 _id 字段创建集群索引:

db := client.Database("db")
cio := bson.D{{"key", bson.D{{"_id", 1}}}, {"unique", true}}
opts := options.CreateCollection().SetClusteredIndex(cio)
db.CreateCollection(context.TODO(), "tea", opts)

文本索引支持对字符串内容进行文本搜索查询。此索引需要字符串字段或字符串数组。MongoDB 支持多种语言的文本搜索。在创建索引时,可以指定默认语言作为选项。

一个集合只能包含一个文本索引。如果要为多个文本字段创建文本索引,必须创建复合索引。文本搜索在复合索引内的所有文本字段上运行。

提示

文本索引不同于功能更强大的 Atlas Full Text Search 索引。我们建议 Atlas 用户使用 Atlas Search。

以下示例在 plot 字段上创建文本索引,并将 italian 作为 sample_mflix.movies 集合中的默认语言:

coll := client.Database("sample_mflix").Collection("movies")
indexModel := mongo.IndexModel{Keys: bson.D{{"plot", "text"}, {"default_language", "italian"}}}
name, err := coll.Indexes().CreateOne(context.TODO(), indexModel)
if err != nil {
panic(err)
}
fmt.Println("Name of Index Created: " + name)
Name of Index Created: plot_text

MongoDB 支持使用 2dsphere 索引包含地理空间坐标数据的查询。2dsphere 索引必须在 GeoJSON 对象字段中。

此索引允许您执行以下操作:

  • 查询地理空间数据以进行包含、交叉和邻近操作。

  • 计算欧几里得平面上的距离,并使用 MongoDB 2.2 及更早版本中使用的“传统坐标对”语法。

sample_mflix.theaters 集合中文档中的 location.geo 字段是一个 GeoJSON 点对象,用于描述剧院的坐标:

{
"_id" : ObjectId("59a47286cfa9a3a73e51e75c"),
"theaterId" : 104,
"location" : {
"address" : {
"street1" : "5000 W 147th St",
"city" : "Hawthorne",
"state" : "CA",
"zipcode" : "90250"
},
"geo" : {
"type" : "Point",
"coordinates" : [
-118.36559,
33.897167
]
}
}
}

以下示例在 location.geo 字段上创建一个 2dsphere 索引:

重要

尝试在地理空间索引所覆盖的字段上创建地理空间索引会导致错误。

indexModel := mongo.IndexModel{
Keys: bson.D{{"location.geo", "2dsphere"}}
}
name, err := coll.Indexes().CreateOne(context.TODO(), indexModel)
if err != nil {
panic(err)
}
fmt.Println("Name of Index Created: " + name)
location.geo_2dsphere

唯一索引可确保索引字段不存储重复值。默认情况下,MongoDB 在创建集合期间会在 _id 字段上创建唯一索引。

要创建唯一索引,请指定要防止重复的字段或字段组合,并将 unique 选项设置为 true

以下示例在 theaterId 字段上创建唯一的降序索引:

indexModel := mongo.IndexModel{
Keys: bson.D{{"theaterId", -1}},
Options: options.Index().SetUnique(true),
}
name, err := coll.Indexes().CreateOne(context.TODO(), indexModel)
if err != nil {
panic(err)
}
fmt.Println("Name of Index Created: " + name)
Name of Index Created: theaterId_-1

您可以删除集合中的任何索引,但 _id字段上的默认唯一索引除外。 要删除索引,请将索引的名称传递给 DropOne() 方法。

title_1sample_mflix.movies以下示例从collection中删除名为 的索引:

coll := client.Database("sample_mflix").Collection("movies")
err := coll.Indexes().DropOne(context.TODO(), "title_1")
if err != nil {
panic(err)
}

要了解有关所提及索引的更多信息,请参阅以下指南:

要了解有关提到的操作的更多信息,请参阅以下指南:

要进一步了解本指南所讨论的任何方法,请参阅以下 API 文档: