Partial Indexes部分索引
On this page本页内容
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
索引,请使用带有partialFilterExpression
选项的db.collection.createIndex()
方法。The partialFilterExpression
option accepts a document that specifies the filter condition using:partialFilterExpression
选项接受一个文档,该文档使用以下内容指定筛选条件:
equality expressions (i.e.等式表达式(即field: value
or using the$eq
operator),field: value
或使用$eq
运算符),$exists: true
expression,表达式,$gt
,$gte
,$lt
,$lte
expressions,表达式,$type
expressions,表达式,$and
operator,运算符,$or
operator,运算符,$in
operator运算符
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 您可以为所有MongoDB索引类型指定一个partialFilterExpression
option for all MongoDB index types. When specifying a partialFilterExpression
for a TTL index on a time series collection, you can only filter on the collection metaField
.partialFilterExpression
选项。为时间序列集合的TTL索引指定partialFilterExpression
时,只能对集合metaField
进行筛选。
See also: 另请参阅:
To learn how to manage indexes in MongoDB Compass, see Manage Indexes.要了解如何在MongoDB Compass中管理索引,请参阅管理索引。
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 }
. rating: { $lt: 8 }
,而索引具有筛选器rating: { $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 Sparse Indexes与稀疏索引的比较
Partial indexes should be preferred over sparse indexes. 部分索引应该优先于稀疏索引。Partial indexes provide the following benefits:部分索引提供以下好处:
Greater control over which documents are indexed.更好地控制对哪些文档进行索引。A superset of the functionality offered by sparse indexes.稀疏索引提供的功能的超集。
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
字段上包含非null
匹配项。
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
字段上的非null
匹配:
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
字段中包含null
匹配项,这是筛选表达式{ email: { $exists: true } }
不允许的:
db.contacts.find( { name: "xyz", email: { $exists: false } } )
Restrictions限制
Starting in MongoDB 5.0, multiple partial indexes can be created using the same key pattern as long as the partialFilterExpression fields do not express equivalent filters.从MongoDB 5.0开始,只要partialFilterExpression
字段不表示等效的筛选器,就可以使用相同的键模式创建多个部分索引。
In earlier versions of MongoDB, creating multiple partial indexes is not allowed when using the same key pattern with different partialFilterExpressions.在早期版本的MongoDB中,当使用相同的键模式和不同的partialFilterExpressions
时,不允许创建多个部分索引。
You cannot specify both the 不能同时指定partialFilterExpression
option and the sparse
option.partialFilterExpression
选项和sparse
选项。
_id
indexes cannot be partial indexes.索引不能是部分索引。
Shard key indexes cannot be partial indexes.分片键索引不能是部分索引。
Examples实例
Create a Partial Index On A Collection在集合上创建部分索引
Consider a collection 考虑一个包含类似以下文档的restaurants
containing documents that resemble the followingrestaurants
集合
{
"_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
:borough
和cuisine
字段的部分索引,只选择对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
:21
:
db.users.insertMany( [
{ username: "david", age: 27 },
{ username: "amanda", age: 25 },
{ 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.insertMany( [
{ username: "david", age: 20 },
{ username: "amanda" },
{ username: "rajiv", age: null }
] )