Partial Indexes部分索引

On this page本页内容

New in version 3.2.版本3.2中的新功能。

Partial indexes only index the documents in a collection that meet a specified filter expression. 部分索引仅对集合中满足指定筛选表达式的文档进行索引。By indexing a subset of the documents in a collection, partial indexes have lower storage requirements and reduced performance costs for index creation and maintenance.通过索引集合中文档的子集,部分索引具有更低的存储需求,并降低了索引创建和维护的性能成本。

Create a Partial Index创建部分索引

To create a partial index, use the db.collection.createIndex() method with the partialFilterExpression option. 要创建partial索引,请使用db.collection.createIndex()方法配合带有partialFilterExpression选项。The partialFilterExpression option accepts a document that specifies the filter condition using:partialFilterExpression选项接受指定筛选条件的文档,该文档使用:

For example, the following operation creates a compound index that indexes only the documents with a rating field greater than 5.例如,下面的操作创建了一个复合索引,该索引只对rating字段大于5的文档进行索引。

db.restaurants.createIndex(
   { cuisine: 1, name: 1 },
   { partialFilterExpression: { rating: { $gt: 5 } } }
)

You can specify a partialFilterExpression option for all MongoDB index types.可以为所有MongoDB索引类型指定partialFilterExpression选项。

Behavior行为

Query Coverage查询覆盖率

MongoDB will not use the partial index for a query or sort operation if using the index results in an incomplete result set.如果使用部分索引导致结果集不完整,MongoDB将不会在查询或排序操作中使用部分索引。

To use the partial index, a query must contain the filter expression (or a modified filter expression that specifies a subset of the filter expression) as part of its query condition.要使用部分索引,查询必须包含筛选器表达式(或指定筛选器表达式子集的修改筛选器表达式)作为其查询条件的一部分。

For example, given the following index:例如,给定以下索引:

db.restaurants.createIndex(
   { cuisine: 1 },
   { partialFilterExpression: { rating: { $gt: 5 } } }
)

The following query can use the index since the query predicate includes the condition rating: { $gte: 8 } that matches a subset of documents matched by the index filter expression rating: { $gt: 5 }:以下查询可以使用索引,因为查询谓词包括条件rating: { $gte: 8 },该评级与索引筛选器表达式rating: { $gt: 5 }匹配的文档子集相匹配:

db.restaurants.find( { cuisine: "Italian", rating: { $gte: 8 } } )

However, the following query cannot use the partial index on the cuisine field because using the index results in an incomplete result set. 但是,下面的查询无法使用cuisine字段上的部分索引,因为使用索引会导致结果集不完整。Specifically, the query predicate includes the condition rating: { $lt: 8 } while the index has the filter rating: { $gt:5 }. 具体来说,查询谓词包括条件评级:{$lt:8},而索引的筛选评级为:{$gt:5}That is, the query { cuisine: "Italian", rating: { $lt: 8 } } matches more documents (e.g. an Italian restaurant with a rating equal to 1) than are indexed.也就是说,查询{ cuisine: "Italian", rating: { $lt: 8 } }匹配的文档(例如评级等于1的意大利餐厅)比索引的文档多。

db.restaurants.find( { cuisine: "Italian", rating: { $lt: 8 } } )

Similarly, the following query cannot use the partial index because the query predicate does not include the filter expression and using the index would return an incomplete result set.类似地,以下查询无法使用部分索引,因为查询谓词不包括筛选表达式,并且使用索引将返回不完整的结果集。

db.restaurants.find( { cuisine: "Italian" } )

Comparison with the sparse Index与稀疏索引的比较

Tip

Partial indexes represent a superset of the functionality offered by sparse indexes and should be preferred over sparse indexes.部分索引代表稀疏索引提供的功能的超集,应该优先于稀疏索引。

Partial indexes offer a more expressive mechanism than Sparse Indexes indexes to specify which documents are indexed.稀疏索引相比,部分索引提供了一种更具表现力的机制来指定哪些文档被索引。

Sparse indexes select documents to index solely based on the existence of the indexed field, or for compound indexes, the existence of the indexed fields.稀疏索引仅根据索引字段的存在来选择要编制索引的文档,对于复合索引,则根据索引字段的存在来选择要编制索引的文档。

Partial indexes determine the index entries based on the specified filter. 部分索引根据指定的筛选器确定索引项。The filter can include fields other than the index keys and can specify conditions other than just an existence check. 筛选器可以包括索引键以外的字段,并且可以指定不只是存在性检查的条件。For example, a partial index can implement the same behavior as a sparse index:例如,部分索引可以实现与稀疏索引相同的行为:

db.contacts.createIndex(
   { name: 1 },
   { partialFilterExpression: { name: { $exists: true } } }
)

This partial index supports the same queries as a sparse index on the name field.此部分索引支持与name字段上的稀疏索引相同的查询。

However, a partial index can also specify filter expressions on fields other than the index key. 但是,部分索引也可以在索引键以外的字段上指定筛选表达式。For example, the following operation creates a partial index, where the index is on the name field but the filter expression is on the email field:例如,以下操作将创建一个部分索引,其中索引位于name字段,而筛选器表达式位于email字段:

db.contacts.createIndex(
   { name: 1 },
   { partialFilterExpression: { email: { $exists: true } } }
)

For the query optimizer to choose this partial index, the query predicate must include a condition on the name field as well as a non-null match on the email field.为了让查询优化器选择这个部分索引,查询谓词必须在name字段中包含一个条件,并在email字段中包含一个非空匹配项。

For example, the following query can use the index because it includes both a condition on the name field and a non-null match on the email field:例如,以下查询可以使用索引,因为它在name字段中包含一个条件,在email字段中包含一个非空匹配:

db.contacts.find( { name: "xyz", email: { $regex: /\.org$/ } } )

However, the following query cannot use the index because it includes a null match on the email field, which is not permitted by the filter expression { email: { $exists: true } }:但是,以下查询无法使用索引,因为它在email字段中包含空匹配项,这是筛选器表达式{ email: { $exists: true } }不允许的:

db.contacts.find( { name: "xyz", email: { $exists: false } } )

Restrictions限制

In MongoDB, you cannot create multiple versions of an index that differ only in the options. 在MongoDB中,不能创建仅在选项上不同的多个索引版本。As such, you cannot create multiple partial indexes that differ only by the filter expression.因此,不能创建仅因筛选器表达式不同而不同的多个部分索引。

You cannot specify both the partialFilterExpression option and the sparse option.不能同时指定partialFilterExpression选项和sparse选项。

MongoDB 3.0 or earlier do not support partial indexes. MongoDB 3.0或更早版本不支持部分索引。To use partial indexes, you must use MongoDB version 3.2 or higher. 要使用部分索引,必须使用MongoDB 3.2版或更高版本。For sharded clusters or replica sets, all nodes must be version 3.2 or higher.对于分片群集或副本集,所有节点必须为3.2版或更高版本。

_id indexes cannot be partial indexes._id索引不能是部分索引。

Shard key indexes cannot be partial indexes.切分键索引不能是部分索引。

Examples示例

Create a Partial Index On A Collection在集合上创建部分索引

Consider a collection restaurants containing documents that resemble the following考虑一个包含类似以下文档的restaurants

{
   "_id" : ObjectId("5641f6a7522545bc535b5dc9"),
   "address" : {
      "building" : "1007",
      "coord" : [
         -73.856077,
         40.848447
      ],
      "street" : "Morris Park Ave",
      "zipcode" : "10462"
   },
   "borough" : "Bronx",
   "cuisine" : "Bakery",
   "rating" : { "date" : ISODate("2014-03-03T00:00:00Z"),
                "grade" : "A",
                "score" : 2
              },
   "name" : "Morris Park Bake Shop",
   "restaurant_id" : "30075445"
}

You could add a partial index on the borough and cuisine fields choosing only to index documents where the rating.grade field is A:您可以在boroughcuisine字段上添加部分索引,选择仅为rating.grade字段为A的文档编制索引:

db.restaurants.createIndex(
   { borough: 1, cuisine: 1 },
   { partialFilterExpression: { 'rating.grade': { $eq: "A" } } }
)

Then, the following query on the restaurants collection uses the partial index to return the restaurants in the Bronx with rating.grade equal to A:然后,以下对restaurants集合的查询使用部分索引返回布朗克斯区rating.grade等于A的餐馆:

db.restaurants.find( { borough: "Bronx", 'rating.grade': "A" } )

However, the following query cannot use the partial index because the query expression does not include the rating.grade field:但是,以下查询无法使用部分索引,因为查询表达式不包括rating.grade字段:

db.restaurants.find( { borough: "Bronx", cuisine: "Bakery" } )

Partial Index with Unique Constraint具有唯一约束的部分索引

Partial indexes only index the documents in a collection that meet a specified filter expression. 部分索引仅对集合中满足指定筛选表达式的文档进行索引。If you specify both the partialFilterExpression and a unique constraint, the unique constraint only applies to the documents that meet the filter expression. 如果同时指定partialFilterExpression唯一约束,则唯一约束仅适用于满足筛选表达式的文档。A partial index with a unique constraint does not prevent the insertion of documents that do not meet the unique constraint if the documents do not meet the filter criteria.如果文档不符合筛选条件,则具有唯一约束的部分索引不会阻止插入不符合唯一约束的文档。

For example, a collection users contains the following documents:例如,集合users包含以下文档:

{ "_id" : ObjectId("56424f1efa0358a27fa1f99a"), "username" : "david", "age" : 29 }
{ "_id" : ObjectId("56424f37fa0358a27fa1f99b"), "username" : "amanda", "age" : 35 }
{ "_id" : ObjectId("56424fe2fa0358a27fa1f99c"), "username" : "rajiv", "age" : 57 }

The following operation creates an index that specifies a unique constraint on the username field and a partial filter expression age: { $gte: 21 }.以下操作将创建一个索引,该索引指定username字段上的唯一约束和部分筛选表达式age: { $gte: 21 }

db.users.createIndex(
   { username: 1 },
   { unique: true, partialFilterExpression: { age: { $gte: 21 } } }
)

The index prevents the insertion of the following documents since documents already exist with the specified usernames and the age fields are greater than 21:索引阻止插入以下文档,因为已存在具有指定用户名的文档,且age字段大于21

db.users.insert( { username: "david", age: 27 } )
db.users.insert( { username: "amanda", age: 25 } )
db.users.insert( { username: "rajiv", age: 32 } )

However, the following documents with duplicate usernames are allowed since the unique constraint only applies to documents with age greater than or equal to 21.但是,允许使用重复用户名的以下文档,因为唯一约束仅适用于age大于或等于21岁的文档。

db.users.insert( { username: "david", age: 20 } )
db.users.insert( { username: "amanda" } )
db.users.insert( { username: "rajiv", age: null } )