索引
在此页面上
Overview
索引是 MongoDB 中为高效查询提供支持的数据结构。它们包含文档中部分数据的副本,以提高查询效率。
如果没有索引,MongoDB 必须扫描集合中的每份文档,从而找到与每个查询相匹配的文档。这些集合扫描很慢,可能会对应用程序的性能产生负面影响。使用索引来限制 MongoDB 扫描的文档数量,可以提高查询效率,促进返回速度。
查询覆盖和性能
当您对 MongoDB 执行查询时,您的查询可以包括以下三个部分:
用于指定您要查找的一个或多个字段和值的查询条件
影响查询执行的选项,例如读关注
用于指定您希望 MongoDB 返回的字段的投影条件(可选)
当查询条件和查询的投影中指定的所有字段都已经被索引,MongoDB 会直接从索引返回结果,而无需扫描集合中的任何文档,也不需要将这些文档加载到内存中。
操作注意事项
若要提高查询性能,请对应用程序查询中经常出现的字段以及其他操作返回的排序结果中经常出现的字段建立索引。您添加的每个索引在活动状态下都会占用磁盘空间和内存,因此您可能需要跟踪索引内存和磁盘使用情况以进行容量规划。此外,当写入操作更新索引字段时,MongoDB 还会更新相关索引。
有关设计数据模型和选择适合您应用程序的索引的更多信息,请参阅 MongoDB 服务器文档中的索引策略和数据建模和索引部分。
列出索引
您可以使用 listIndexes()
方法列出集合的所有索引。listIndexes() 方法接受一个可选的 ListIndexesOptions 参数。listIndexes()
方法返回类型为 ListIndexesCursor 的对象。
以下代码使用 listIndexes()
方法列出集合中的所有索引:
// List the indexes on the collection and output them as an array const result = await collection.listIndexes().toArray(); // Print the list of indexes console.log("Existing indexes:\n"); for(const doc in result){ console.log(doc); }
索引类型
MongoDB 支持多种索引类型来进行数据查询。以下部分描述了最常见的索引类型,并提供了创建每种索引类型的示例代码。
单字段索引
单字段索引是指可提高特定查询的性能的索引,而此类查询会对文档的单个字段指定升序或降序排序顺序。
以下示例使用 createIndex()
方法对 sample_mflix
数据库的 movies
集合的 title
字段创建升序索引。
const database = client.db("sample_mflix"); const movies = database.collection("movies"); // Create an ascending index on the "title" field in the // "movies" collection. const result = await movies.createIndex({ title: 1 }); console.log(`Index created: ${result}`);
以下是一个使用上述所建索引实现高效查询的示例。
// Define the query parameters const query = { title: "Batman" } const sort = { title: 1 }; const projection = { _id: 0, title: 1 }; // Execute the query using the defined parameters const cursor = movies .find(query) .sort(sort) .project(projection);
如要了解更多信息,请参阅单字段索引。
复合索引
复合索引可提高为文档的多个字段指定升序或降序排序顺序的查询的性能。您必须为索引中的每个字段指定方向(升序或降序)。
以下示例使用 createIndex()
方法在 sample_mflix
数据库的 movies
集合中的 type
和 genre
字段上创建复合索引。
// Connect to the "sample_mflix" database const database = client.db("sample_mflix"); // Access the database's "movies" collection const movies = database.collection("movies"); // Create an ascending index on the "type" and "genre" fields // in the "movies" collection. const result = await movies.createIndex({ type: 1, genre: 1 }); console.log(`Index created: ${result}`);
以下是一个使用上述所建索引实现高效查询的示例。
// Define a query to find movies in the "Drama" genre const query = { type: "movie", genre: "Drama" }; // Define sorting criteria for the query results const sort = { type: 1, genre: 1 }; // Include only the type and genre fields in the query results const projection = { _id: 0, type: 1, genre: 1 }; // Execute the query using the defined criteria and projection const cursor = movies .find(query) .sort(sort) .project(projection);
要了解更多信息,请参阅复合索引。
多键索引(数组字段索引)
多键索引可提高对包含数组值的字段的查询性能。
您可以通过调用 createIndex()
方法,对具有数组值的字段创建多键索引。以下代码将对 sample_mflix
数据库 movies
集合中的 cast
字段创建升序索引:
const database = client.db("sample_mflix"); const movies = database.collection("movies"); // Create a multikey index on the "cast" field in the "movies" collection const result = await movies.createIndex({ cast: 1 });
以下代码会查询多键索引以查找 cast
字段值包含 "Viola Davis"
的文档:
const query = { cast: "Viola Davis" }; const projection = { _id: 0, cast: 1 , title: 1 }; // Perform a find operation with the preceding filter and projection const cursor = movies .find(query) .project(projection);
在查询覆盖、索引绑定计算和排序行为方面,多键索引的行为与非多键索引不同。有关多键索引的完整解释,包括对其行为和限制的讨论,请参阅 MongoDB Server 手册中的多键索引页面。
聚集索引
聚集索引是指可提高针对集群化集合的插入、更新和删除操作的性能的索引。集群化集合可存储按聚集索引键值排序的文档。
要创建聚集索引,请在 CollectionOption
中指定 clusteredIndex
选项。clusteredIndex
选项必须将 _id
字段指定为键,并将唯一字段指定为 true
。
以下示例使用 createCollection()
方法在 tea
数据库的 vendors
集合中的 _id
字段上创建聚集索引。
const db = client.db('tea'); await db.createCollection('ratings', { clusteredIndex: { key: { _id: 1 }, unique: true } });
Text Indexes
文本索引支持对字符串内容进行文本搜索查询。这些索引可以包括任何值为字符串或字符串元素数组的字段。
MongoDB 支持多种语言的文本搜索,因此在创建索引时,有选项可供您指定默认语言。您还可以指定一个权重选项,来优先处理索引中的某些文本字段。权重表示这些字段相对于其他索引字段的重要性。
要了解有关文本搜索的更多信息,请参阅 文本搜索查询指南。
以下示例使用createIndex()
方法执行以下操作:
在
blogPosts
集合中的title
和body
字段上创建一个text
索引将
english
指定为默认语言将
body
的字段权重设为10
,并将title
的字段权重设为3
// Get the database and collection on which to create the index const myDB = client.db("testDB"); const myColl = myDB.collection("blogPosts"); // Create a text index on the "title" and "body" fields const result = await myColl.createIndex( { title: "text", body: "text" }, { default_language: "english" }, { weights: { body: 10, title: 3 } } );
以下查询使用了在上述代码中创建的文本索引:
// Query for documents where body or title contain "life ahead" const query = { $text: { $search: "life ahead" } }; // Show only the title field const projection = { _id: 0, title: 1 }; // Execute the find operation const cursor = myColl.find(query).project(projection);
要了解有关文本索引的更多信息,请参阅服务器手册中的文本索引。
地理空间索引
MongoDB 支持使用 2dsphere 索引查询地理空间坐标数据。借助 2dsphere 索引,您可以针对地理空间数据进行包含、相交和邻近范围方面的查询。有关使用 MongoDB Node.js 驱动程序查询地理空间数据的更多信息,请阅读搜索地理空间指南。
要创建 2dsphere 索引,您必须指定仅包含 GeoJSON 对象的字段。有关该类型的详细信息,请参阅 MongoDB 服务器手册中有关以下内容的页面: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 ] } } }
以下示例使用 createIndexes()
方法对 sample_mflix
数据库的 theaters
集合的 location.geo
字段创建 2dsphere
索引,以启用地理空间搜索。
const database = client.db("sample_mflix"); const movies = database.collection("movies"); /* Create a 2dsphere index on the "location.geo" field in the "movies" collection */ const result = await movies.createIndex({ "location.geo": "2dsphere" }); // Print the result of the index creation console.log(`Index created: ${result}`);
MongoDB 还支持 2d
索引,用于计算欧几里德平面上的距离,以及处理 MongoDB 2.2 及更早版本中使用的“旧版坐标对”语法。要了解更多信息,请参阅地理空间查询。
Unique Indexes
唯一索引可确保索引字段不存储重复值。默认情况下,MongoDB 在创建集合期间会在 _id
字段上创建唯一索引。要创建唯一索引,请指定要防止重复的字段或字段组合,并将 unique
选项设置为 true
。
以下示例使用 createIndex()
方法在 sample_mflix
数据库 theaters
集合中的 theaterId
字段上创建唯一索引。
const database = client.db("sample_mflix"); const movies = database.collection("movies"); // Create a unique index on the "theaterId" field in the "theaters" collection. const result = await movies.createIndex({ theaterId: 1 }, { unique: true }); console.log(`Index created: ${result}`);
如果您的写操作违反了唯一索引的规则,即尝试对索引字段存储重复的值, MongoDB 将抛出类似以下的报错:
E11000 duplicate key error index
要了解详情,请参阅唯一索引。
搜索索引
Atlas Search 功能允许您执行全文搜索。要了解详情,请参阅 Atlas Search 文档。
在对 Atlas 集合进行搜索之前,您必须先在集合上创建一个 Atlas Search 索引。Atlas Search 索引是一种数据结构,它会以可搜索的格式对数据进行分类。
您可以使用以下方法管理 Atlas Search 索引:
createSearchIndex()
createSearchIndexes()
listSearchIndexes()
updateSearchIndex()
dropSearchIndex()
以下各节提供了使用上述方法管理 Atlas Search 索引的代码示例。
创建搜索索引
您可以使用 createSearchIndex() 和 createSearchIndexes() 方法创建新的搜索索引。
以下代码展示了如何使用 createSearchIndex()
方法创建名为 search1
的索引:
// Create a search index const index1 = { name: "search1", definition: { "mappings": { "dynamic": true } } } await collection.createSearchIndex(index1);
当连接到 MongoDB Server v6.0.11 及更新的 v6 版本时,或连接到 v7.0.2 及更新的 v7 版本时,您可以使用驱动程序在集合上创建 Atlas Vector Search 索引。有关此功能的更多信息,请参阅 Atlas Vector Search 文档。
以下代码展示了如何使用 createSearchIndex()
方法创建搜索索引,其中 type
字段为 vectorSearch
:
// Create a Vector Search index const vectorSearchIdx = { name: "vsidx1", type: "vectorSearch", definition: { fields: [{ type: "vector", numDimensions: 384, path: "summary", similarity: "dotProduct" }] } } await collection.createSearchIndex(vectorSearchIdx);
搜索索引列表
您可以使用 listSearchIndexes() 方法返回一个包含给定集合搜索索引的游标。listSearchIndexes()
方法接受一个可选的字符串参数 name
,如提供该参数,则仅返回名称匹配的索引。它还接受一个可选的 aggregateOptions 参数。
下面的代码使用 listSearchIndexes()
方法列出集合中的 Atlas Search 索引:
// List search indexes const result = await collection.listSearchIndexes().toArray(); console.log("Existing search indexes:\n"); for (const doc in result) { console.log(doc); }
更新搜索索引
您可以使用 updateSearchIndex() 方法更新搜索索引。
以下代码演示如何使用 updateSearchIndex()
方法更新名为 search1
的索引,为 description
字段指定字符串类型:
// Update a search index const index2 = { "mappings": { "dynamic": true, "fields": { "description": { "type": "string" } } } } await collection.updateSearchIndex("search1", index2);
删除搜索索引
您可以使用 dropSearchIndex() 方法删除 Atlas Search 索引。
以下代码展示如何使用 dropSearchIndex()
方法删除名为 search1
的索引:
// Dropping (deleting) a search index await collection.dropSearchIndex("search1");