索引
概述
索引是支持在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 服务器手册中的 多键索引页面。
聚集索引
聚集索引是提高对聚集集合的插入、更新和删除操作性能的索引。聚集集合按聚集索引键值存储文档。
要创建聚集索引,请在CollectionOption中指定clusteredIndex选项。必须指定clusteredIndex选项,将_id字段作为键,并将唯一字段指定为true。
以下示例使用createCollection()方法在tea数据库的vendors集合中的_id字段上创建聚集索引。
const db = client.db('tea'); await db.createCollection('ratings', { clusteredIndex: { key: { _id: 1 }, unique: true } });
文本索引
文本索引支持对字符串内容的文本搜索查询。这些索引可以包括任何值是字符串或字符串元素数组的字段。
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 及更早版本中使用的“传统坐标对”语法。有关更多信息,请参阅 地理空间查询。
唯一索引
唯一索引 确保索引字段不存储重复值。默认情况下,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 索引是一种将数据分类为可搜索格式的数据结构。
您可以使用以下方法来管理您的搜索索引
createSearchIndex()createSearchIndexes()listSearchIndexes()updateSearchIndex()dropSearchIndex()
以下各节提供了使用上述每个方法来管理搜索索引的代码示例。
创建搜索索引
您可以使用 createSearchIndex() 和 createSearchIndexes() 方法来创建新的搜索索引。
以下代码演示了如何使用 createSearchIndex() 方法创建一个名为 search1 的索引。
// Create a search index const index1 = { name: "search1", definition: { "mappings": { "dynamic": true } } } await collection.createSearchIndex(index1);
当连接到 MongoDB 服务器 v6.0.11 及更高版本,或 v7.0.2 及更高版本时,您可以使用驱动程序在集合上创建 Atlas 向量搜索索引。有关此功能的更多信息,请参阅Atlas 向量搜索文档。
以下代码演示了如何使用 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() 方法列出集合中的搜索索引
// 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()方法来删除搜索索引。
以下代码展示了如何使用dropSearchIndex()方法来删除名为search1的索引
// Dropping (deleting) a search index await collection.dropSearchIndex("search1");