索引
在此页面上
Overview
在本指南中,您可以学习;了解如何在PyMongo中使用索引。 索引可以提高查询效率,并为查询和存储文档添加附加功能。
如果没有索引,MongoDB 必须扫描集合中的每个文档,以查找与每个查询匹配的文档。 这些集合扫描很慢,可能会对应用程序的性能产生负面影响。 但是,如果查询存在适当的索引,MongoDB 就可以使用该索引来限制必须检查的文档。
操作注意事项
若要提高查询性能,请对应用程序查询中经常出现的字段以及其他操作返回的排序结果中经常出现的字段建立索引。您添加的每个索引在活动状态下都会占用磁盘空间和内存,因此您应当跟踪索引内存和磁盘使用情况以进行容量规划。此外,当写入操作更新索引化字段时,MongoDB 还须更新相关索引。
由于 MongoDB 支持动态模式,因此应用程序可以查询事先未知名称或任意名称的字段。 MongoDB 4.2引入了通配符索引来帮助支持这些查询。 通配符索引并不是为了取代基于工作负载的索引规划而设计的。
有关设计数据模型和选择适合应用程序的索引的更多信息,请参阅MongoDB Server手册中的数据建模和索引指南。
样本数据
本指南中的示例使用Atlas示例数据集中的
sample_mflix.movies
集合。 要学习;了解如何创建免费的MongoDB Atlas 群集并加载示例数据集,请参阅PyMongo入门 。
索引类型
单字段索引和复合索引
单字段索引
单字段索引是对集合文档中的单字段进行引用的索引。其提高了单字段查询和排序性能,并支持 TTL 索引,可在一定时间后或特定时钟时间自动从集合中删除文档。
注意
_id_
索引是单字段索引的一个示例。创建新集合时,会在 _id
字段上自动创建此索引。
以下示例将对 title
字段按升序创建索引:
movies.create_index("title")
以下是前面代码示例中创建的索引涵盖的查询示例:
query = { "title": "Batman" } sort = [("title", 1)] cursor = movies.find(query).sort(sort)
要了解更多信息,请参阅 MongoDB Server 手册中的单字段索引。
复合索引
复合索引包含对集合文档中多个字段的引用,从而提高查询和排序性能。
以下示例在 type
和 genre
字段上创建复合索引:
movies.create_index([("type", pymongo.ASCENDING), ("genre", pymongo.ASCENDING)])
以下是使用前面代码示例中创建的索引的查询示例:
query = { "type": "movie", "genre": "Drama" } sort = [("type", pymongo.ASCENDING), ("genre", pymongo.ASCENDING)] cursor = movies.find(query).sort(sort)
有关更多信息,请参阅 MongoDB Server 手册中的复合索引。
多键索引(数组字段索引)
多键索引可提高使用包含数组值的索引指定字段的查询性能。 您可以使用与单字段或复合索引相同的语法来定义多键索引。
以下示例在cast
字段上创建多键索引:
result = movies.create_index("cast")
以下是使用前面代码示例中创建的索引的查询示例:
query = { "cast": "Viola Davis" } cursor = movies.find(query)
多键索引在查询覆盖、索引绑定计算和排序行为方面的行为与其他索引不同。要学习;了解有关多键索引的更多信息,包括对其行为和限制的讨论,请参阅MongoDB Server手册中的多键索引指南。
Atlas Search和 Vector Search 索引
您可以使用 PyMongo 管理 Atlas Search 和 Atlas Vector Search 索引。索引指定了搜索行为以及要索引的字段。
Atlas Search 功能使您能够对 MongoDB Atlas 上托管的集合执行全文搜索。Atlas Search 索引指定了搜索行为以及要索引的字段。
Atlas Vector Search 使您能够对存储在 MongoDB Atlas 中的向量嵌入执行语义搜索。向量搜索索引定义要查询的向量嵌入的索引,以及要用于预过滤数据的布尔值、日期、objectId、数字、字符串或 UUID 值。
您可以在集合上调用以下方法来管理Atlas Search和 Vector Search 索引:
create_search_index()
create_search_indexes()
list_search_indexes()
update_search_index()
drop_search_index()
注意
Atlas Search 索引管理方法异步运行。驱动程序方法可以在确认成功运行前返回。要确定索引的当前状态,请调用 list_search_indexes()
方法。
以下各节将提供代码示例,演示如何使用上述每种方法。
创建搜索索引
可以使用 create_search_index() 和 create_search_indexes() 方法创建 Atlas Search 索引或 Atlas Vector Search 索引。
以下代码示例展示了如何创建单个 Atlas Search 索引:
index = { "definition": { "mappings": { "dynamic": True } }, "name": "<index name>", } collection.create_search_index(index)
下面的代码示例展示了如何使用 SearchIndexModel 对象创建单个 Atlas Vector Search 索引:
from pymongo.operations import SearchIndexModel search_index_model = SearchIndexModel( definition={ "fields": [ { "type": "vector", "numDimensions": <number of dimensions>, "path": "<field to index>", "similarity": "<select from euclidean, cosine, dotProduct>" } ] }, name="<index name>", type="vectorSearch", ) collection.create_search_index(model=search_index_model)
您可以使用 create_search_indexes() 方法来创建多个索引。这些索引可以是 Atlas Search 或 Vector Search 搜索索引。create_search_indexes()
方法采用与要创建的每个索引对应的 SearchIndexModel
对象的列表。
以下代码示例展示了如何创建 Atlas Search 索引和 Atlas Vector Search 索引:
search_idx = SearchIndexModel( definition ={ "mappings": { "dynamic": True } }, name="my_index", ) vector_idx = SearchIndexModel( definition={ "fields": [ { "type": "vector", "numDimensions": <number of dimensions>, "path": "<field to index>", "similarity": "<select from euclidean, cosine, dotProduct>" } ] }, name="my_vector_index", type="vectorSearch", ) indexes = [search_idx, vector_idx] collection.create_search_indexes(models=indexes)
搜索索引列表
您可以使用 list_search_indexes() 方法来获取有关集合的 Atlas Search 和 Vector Search 索引的信息。
以下代码示例显示如何打印集合的搜索索引列表:
results = list(collection.list_search_indexes()) for index in results: print(index)
更新搜索索引
您可以使用 update_search_index() 方法更新 Atlas Search 或 Vector Search 索引。
以下代码示例展示如何更新 Atlas Search 索引:
new_index_definition = { "mappings": { "dynamic": False } } collection.update_search_index("my_index", new_index)
以下代码示例展示如何更新 Atlas Vector Search 索引:
new_index_definition = { "fields": [ { "type": "vector", "numDimensions": 1536, "path": "<field to index>", "similarity": "euclidean" }, ] } collection.update_search_index("my_vector_index", new_index_definition)
删除搜索索引
您可以使用 drop_search_index() 方法删除 Atlas Search 或 Vector Search 索引。
以下代码展示了如何从集合中删除搜索索引:
collection.drop_search_index("my_index")
Text Indexes
文本索引支持对字符串内容进行文本搜索查询。这些索引可以包括任何值为字符串或字符串元素数组的字段。MongoDB 还支持各种语言的文本搜索。在创建索引时,可以指定默认语言作为选项。
提示
MongoDB提供改进的全文搜索解决方案Atlas Search。要学习;了解有关Atlas Search索引及其使用方法的更多信息,请参阅本页的Atlas Search和 Vector Search 索引部分。
单个字段上的文本索引
以下示例在 plot
字段上创建一个文本索引:
movies.create_index( [( "plot", "text" )] )
以下是使用前面代码示例中创建的索引的查询示例:
query = { "$text": { "$search": "a time-traveling DeLorean" } } cursor = movies.find(query)
多个字段上的文本索引
一个集合只能包含一个文本索引。 如果要为多个文本字段创建文本索引,请创建复合索引。 对复合索引中的所有文本字段运行文本搜索。
以下示例为title
和genre
字段创建复合文本索引:
result = myColl.create_index( [("title", "text"), ("genre", "text")], default_language="english", weights={ "title": 10, "genre": 3 } )
地理空间索引
MongoDB 支持使用 2dsphere 索引查询地理空间坐标数据。借助 2dsphere
索引,您可以针对地理空间数据进行包含、相交和邻近范围方面的查询。有关查询地理空间数据的更多信息,请参阅地理空间查询。
要创建2dsphere
索引,您必须指定仅包含GeoJSON 对象的字段。 有关此类型的更多详细信息,请参阅 MongoDB Server 手册中的GeoJSON 对象指南。
以下样本文档中的 location.geo
字段来自 sample_mflix
数据库中的 theaters
集合,且为用于描述影院坐标的 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
索引:
theaters.create_index( [( "location.geo", "2dsphere" )] )
MongoDB还支持2d
索引,用于计算欧几里得平面上的距离,以及使用legacy coordinate pairs MongoDB2.2及更早版本中使用的“ ”语法。有关更多信息,请参阅 MongoDB Server 手册中的地理空间查询指南。
Unique Indexes
唯一索引可确保索引字段不存储重复值。 默认情况下,MongoDB 在创建集合期间会在_id
字段上创建唯一索引。 要创建唯一索引,请执行以下步骤:
指定要防止重复的字段或字段组合。
将
unique
选项设置为“True”。
创建唯一索引
以下示例在theaterId
字段上创建一个降序唯一索引:
theaters.create_index("theaterId", unique=True)
有关更多信息,请参阅 MongoDB Server 手册中的“唯一索引”指南。
通配符索引 (Wildcard Indexes)
通配符索引可对未知或任意字段进行查询。如果您使用的是动态模式,则这些索引可能很有用。
创建通配符索引
以下示例将对 location
字段的所有值(包括嵌套在子文档和数组中的值)创建升序通配符索引:
movies.create_index({ "location.$**": pymongo.ASCENDING })
有关更多信息,请参阅 MongoDB 服务器手册中的通配符索引页面。
聚集索引
集群化索引指示集合存储按键值排序的文档。 要创建集群索引,请在创建集合时执行以下步骤:
使用
_id
字段作为键来指定集群索引选项。将唯一字段设置为
True
。
创建集群索引
以下示例在新的movie_reviews
集合中的_id
字段上创建集群索引:
sample_mflix.create_collection("movies", clusteredIndex={ "key": { "_id": 1 }, "unique": True })
删除索引
您可以删除针对 _id
字段的所有未使用索引,但默认唯一索引除外。
以下部分介绍如何删除单个索引或删除集合中的所有索引。
删除单个索引
将索引实例或索引名称传递给drop_index()
方法,以从集合中删除索引。
以下示例从movies
集合中删除名为"_title_"
的索引:
movies.drop_index("_title_")
注意
不能从复合文本索引中删除单个字段。您必须删除整个索引,然后创建新索引,才能更新索引字段。
删除所有索引
从 MongoDB 4.2 开始,您可以在集合上调用 drop_indexes()
方法来删除所有索引:
collection.drop_indexes()
对于早期版本的 MongoDB,请将"*"
作为参数传递给对集合上drop_index()
的调用:
collection.drop_index("*")
故障排除
DuplicateKeyException
如果您执行的写入操作存储了违反唯一索引的重复值,则驱动程序会引发DuplicateKeyException
,并且 MongoDB 会抛出类似于以下内容的错误:
E11000 duplicate key error index
更多信息
要学习;了解有关MongoDB中索引的更多信息,请参阅MongoDB Server手册中的索引指南。
API 文档
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: