On this page本页内容
The bounds of an index scan define the portions of an index to search during a query. 索引扫描的边界定义了查询期间要搜索的索引部分。When multiple predicates over an index exist, MongoDB will attempt to combine the bounds for these predicates, by either intersection or compounding, in order to produce a scan with smaller bounds.当索引上存在多个谓词时,MongoDB将尝试通过交集或复合的方式组合这些谓词的边界,以便生成具有较小边界的扫描。
Bounds intersection refers to a logical conjunction (i.e. 边界交集是指多个边界的逻辑连接(即AND
) of multiple bounds. AND
)。For instance, given two bounds 例如,给定两个边界[ [ 3, Infinity ] ]
and [ [ -Infinity, 6 ] ]
, the intersection of the bounds results in [ [ 3, 6 ] ]
.[ [ 3, Infinity ] ]
和[ [ -Infinity, 6 ] ]
,边界的交集产生[ [3, 6 ] ]
。
Given an indexed array field, consider a query that specifies multiple predicates on the array and can use a multikey index. 给定一个索引数组字段,请考虑一个在数组上指定多个谓词并可以使用多键索引的查询。MongoDB can intersect multikey index bounds if an 如果$elemMatch
joins the predicates.$elemMatch
连接谓词,MongoDB可以与多键索引边界相交。
For example, a collection 例如,集合survey
contains documents with a field item
and an array field ratings
:survey
包含具有字段项和数组字段ratings
的文档:
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] } { _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
Create a multikey index on the 在评级数组上创建多键索引:ratings
array:
db.survey.createIndex( { ratings: 1 } )
The following query uses 以下查询使用$elemMatch
to require that the array contains at least one single element that matches both conditions:$elemMatch
要求数组至少包含一个与两个条件匹配的元素:
db.survey.find( { ratings : { $elemMatch: { $gte: 3, $lte: 6 } } } )
Taking the predicates separately:分别使用谓词:
$gte: 3
) are [ [ 3, Infinity ] ]
;$gte: 3
)的边界为[ [ 3, Infinity ] ]
;$lte: 6
) are [ [ -Infinity, 6 ] ]
.$lte:6
)的边界为[ [ -Infinity, 6 ] ]
。Because the query uses 由于查询使用$elemMatch
to join these predicates, MongoDB can intersect the bounds to:$elemMatch
连接这些谓词,MongoDB可以将边界相交到:
ratings: [ [ 3, 6 ] ]
If the query does not join the conditions on the array field with 如果查询没有将数组字段上的条件与$elemMatch
, MongoDB cannot intersect the multikey index bounds. Consider the following query:$elemMatch
连接起来,MongoDB将无法与多键索引边界相交。考虑以下查询:
db.survey.find( { ratings : { $gte: 3, $lte: 6 } } )
The query searches the 该查询在ratings
array for at least one element greater than or equal to 3 and at least one element less than or equal to 6. ratings
数组中搜索至少一个大于或等于3的元素和至少一个小于或等于6的元素。Because a single element does not need to meet both criteria, MongoDB does not intersect the bounds and uses either 因为单个元素不需要同时满足这两个条件,所以MongoDB不与边界相交,而是使用[ [ 3, Infinity ] ]
or [ [ -Infinity, 6 ] ]
. [ [ 3, Infinity ] ]
或[ [ -Infinity, 6 ] ]
。MongoDB makes no guarantee as to which of these two bounds it chooses.MongoDB不保证它选择这两个边界中的哪一个。
Compounding bounds refers to using bounds for multiple keys of compound index. 复合边界是指对复合索引的多个键使用边界。For instance, given a compound index 例如,给定一个复合索引{ a: 1, b: 1 }
with bounds on field a
of [ [3, Infinity ] ]
and bounds on field b
of [ [ -Infinity, 6 ]]
, compounding the bounds results in the use of both bounds:{ a: 1, b: 1 }
,域a
的边界为[ [3, Infinity ] ]
,域b
的边界为[ [ -Infinity, 6 ]]
,复合边界会导致使用两个边界:
{ a: [ [ 3, Infinity ] ], b: [ [ -Infinity, 6 ] ] }
If MongoDB cannot compound the two bounds, MongoDB always constrains the index scan by the bound on its leading field, in this case, 如果MongoDB不能复合这两个边界,MongoDB总是通过其前导字段上的边界约束索引扫描,在这种情况下,a: [ [ 3, Infinity ] ]
.a: [ [ 3, Infinity ] ]
。
Consider a compound multikey index; i.e. a compound index where one of the indexed fields is an array. 考虑一个复合多键索引;即,其中一个索引字段是数组的复合索引。For example, a collection 例如,survey
contains documents with a field item
and an array field ratings
:survey
调查包含具有字段item
和数组字段ratings
的文档:
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] } { _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
Create a compound index on the 在item
field and the ratings
field:item
字段和ratings
字段上创建复合索引:
db.survey.createIndex( { item: 1, ratings: 1 } )
The following query specifies a condition on both keys of the index:以下查询指定索引的两个键上的条件:
db.survey.find( { item: "XYZ", ratings: { $gte: 3 } } )
Taking the predicates separately:分别使用谓词:
item: "XYZ"
predicate are [ [ "XYZ", "XYZ" ] ]
;item: "XYZ"
谓词项的边界为[ [ "XYZ", "XYZ" ] ]
;ratings: { $gte: 3 }
predicate are [ [ 3, Infinity ] ]
.ratings: { $gte: 3 }
谓词的边界为[ [ 3, Infinity ] ]
。MongoDB can compound the two bounds to use the combined bounds of:MongoDB可以复合这两个边界以使用以下组合边界:
{ item: [ [ "XYZ", "XYZ" ] ], ratings: [ [ 3, Infinity ] ] }
Changed in version 3.4.在版本3.4中更改。
Starting in MongoDB 3.4, for multikey indexes created using MongoDB 3.4 or later, MongoDB keeps track of which indexed field or fields cause an index to be a multikey index. 从MongoDB 3.4开始,对于使用MongoDB 3.4或更高版本创建的多键索引,MongoDB会跟踪哪些索引字段会导致索引成为多键索引。Tracking this information allows the MongoDB query engine to use tighter index bounds.跟踪此信息允许MongoDB查询引擎使用更严格的索引边界。
The aforementioned compound index is on the scalar field [1] 上述复合索引位于标量字段[1] item
and the array field ratings
:item
和数组字段ratings
上:
db.survey.createIndex( { item: 1, ratings: 1 } )
For the WiredTiger and the In-Memory storage engines, if a query operation specifies multiple predicates on the indexed scalar field(s) of a compound multikey index created in MongoDB 3.4 or later, MongoDB will intersect the bounds for the field.对于WiredTiger和内存存储引擎,如果查询操作在MongoDB 3.4或更高版本中创建的复合多键索引的索引标量字段上指定多个谓词,MongoDB将与字段的边界相交。
For example, the following operation specifies a range query on the scalar field as well as a range query on the array field:例如,以下操作指定标量字段上的范围查询以及数组字段上的范围查询:
db.survey.find( { item: { $gte: "L", $lte: "Z"}, ratings : { $elemMatch: { $gte: 3, $lte: 6 } } } )
MongoDB will intersect the bounds for MongoDB将item
to [ [ "L", "Z" ] ]
and ratings to [[3.0, 6.0]]
to use the combined bounds of:item
的边界与[ [ "L", "Z" ] ]
相交,将rating
的边界与[[3.0, 6.0]]
相交,以使用以下组合边界:
"item" : [ [ "L", "Z" ] ], "ratings" : [ [3.0, 6.0] ]
For another example, consider where the scalar fields belong to a nested document. 例如,考虑标量字段属于嵌套文档的位置。For instance, a collection 例如,集合survey
contains the following documents:survey
包含以下文档:
{ _id: 1, item: { name: "ABC", manufactured: 2016 }, ratings: [ 2, 9 ] } { _id: 2, item: { name: "XYZ", manufactured: 2013 }, ratings: [ 4, 3 ] }
Create a compound multikey index on the scalar fields 在标量字段"item.name"
, "item.manufactured"
, and the array field ratings
:"item.name"
、"item.manufactured"
和数组字段ratings
上创建复合多键索引:
db.survey.createIndex( { "item.name": 1, "item.manufactured": 1, ratings: 1 } )
Consider the following operation that specifies query predicates on the scalar fields:考虑以下在标量字段上指定查询谓词的操作:
db.survey.find( { "item.name": "L" , "item.manufactured": 2012 } )
For this query, MongoDB can use the combined bounds of:对于此查询,MongoDB可以使用以下组合边界:
"item.name" : [ ["L", "L"] ], "item.manufactured" : [ [2012.0, 2012.0] ]
Earlier versions of MongoDB cannot combine these bounds for the scalar fields.早期版本的MongoDB无法组合标量字段的这些边界。
[1] | { a: { b: { c: 5, d: 5 } } } , c and d are scalar fields where as a and b are not.{ a: { b: { c: 5, d: 5 } } } 中,c 和d 是标量字段,其中a和b不是。 |
If an array contains embedded documents, to index on fields contained in the embedded documents, use the dotted field name in the index specification. 如果数组包含嵌入文档,要对嵌入文档中包含的字段进行索引,请在索引规范中使用虚线字段名称。For instance, given the following array of embedded documents:例如,给定以下嵌入文档数组:
ratings: [ { score: 2, by: "mn" }, { score: 9, by: "anon" } ]
The dotted field name for the score
field is "ratings.score"
.score
字段的dotted
字段名称为"ratings.score"
。
Consider a collection 假设集合survey2
contains documents with a field item
and an array field ratings
:survey2
包含具有字段item
和数组字段ratings
的文档:
{ _id: 1, item: "ABC", ratings: [ { score: 2, by: "mn" }, { score: 9, by: "anon" } ] } { _id: 2, item: "XYZ", ratings: [ { score: 5, by: "anon" }, { score: 7, by: "wv" } ] }
Create a compound index on the non-array field 在非数组字段item
as well as two fields from an array ratings.score
and ratings.by
:item
以及数组ratings.score
和ratings.by
中的两个字段上创建复合索引:
db.survey2.createIndex( { "item": 1, "ratings.score": 1, "ratings.by": 1 } )
The following query specifies a condition on all three fields:以下查询指定了所有三个字段的条件:
db.survey2.find( { item: "XYZ", "ratings.score": { $lte: 5 }, "ratings.by": "anon" } )
Taking the predicates separately:分别使用谓词:
item: "XYZ"
predicate are [ [ "XYZ", "XYZ" ] ]
;item: "XYZ"
谓词的边界为[ [ "XYZ", "XYZ" ] ]
;score: { $lte: 5 }
predicate are [ [ -Infinity, 5 ] ]
;score: { $lte: 5 }
谓词的边界为[ [ -Infinity, 5 ] ]
;by: "anon"
predicate are [ "anon", "anon" ]
.by: "anon"
谓词的边界为[ "anon", "anon" ]
。MongoDB can compound the bounds for the MongoDB可以根据查询谓词和索引键值,将item
key with either the bounds for "ratings.score"
or the bounds for "ratings.by"
, depending upon the query predicates and the index key values. item
键的边界与"ratings.score"
的边界或"ratings.by"
的边界复合。MongoDB makes no guarantee as to which bounds it compounds with the MongoDB不保证它与item
field. item
字段复合的边界。For instance, MongoDB will either choose to compound the 例如,MongoDB将选择将item
bounds with the "ratings.score"
bounds:item
边界与"ratings.score"
边界复合:
{ "item" : [ [ "XYZ", "XYZ" ] ], "ratings.score" : [ [ -Infinity, 5 ] ], "ratings.by" : [ [ MinKey, MaxKey ] ] }
Or, MongoDB may choose to compound the 或者,MongoDB可以选择将item
bounds with "ratings.by"
bounds:item
边界与"ratings.by"
边界复合:
{ "item" : [ [ "XYZ", "XYZ" ] ], "ratings.score" : [ [ MinKey, MaxKey ] ], "ratings.by" : [ [ "anon", "anon" ] ] }
However, to compound the bounds for 但是,要将"ratings.score"
with the bounds for "ratings.by"
, the query must use $elemMatch
. "ratings.score"
的边界与"ratings.by"
的边界复合,查询必须使用$elemMatch
。See Compound Bounds of Index Fields from an Array for more information.有关详细信息,请参阅数组中索引字段的复合边界。
To compound together the bounds for index keys from the same array:要将同一数组中索引键的边界组合在一起,请执行以下操作:
$elemMatch
on that path.$elemMatch
在字段上指定谓词。For a field in an embedded document, the dotted field name, such as 对于嵌入文档中的字段,虚线字段名(如"a.b.c.d"
, is the field path for d
. "a.b.c.d"
)是d
的字段路径。To compound the bounds for index keys from the same array, the 要复合来自同一数组的索引键的边界,$elemMatch
must be on the path up to but excluding the field name itself; i.e. "a.b.c"
.$elemMatch
必须位于到但不包括字段名本身的路径上;即"a.b.c"
。
For instance, create a compound index on the 例如,在ratings.score
and the ratings.by
fields:ratings.score
和ratings.by
字段上创建复合索引:
db.survey2.createIndex( { "ratings.score": 1, "ratings.by": 1 } )
The fields "ratings.score"
and "ratings.by"
share the field path ratings
. "ratings.score"
和"ratings.by"
字段共享字段路径评级。The following query uses 以下查询在字段$elemMatch
on the field ratings
to require that the array contains at least one single element that matches both conditions:ratings
上使用$elemMatch
来要求数组至少包含一个匹配这两个条件的元素:
db.survey2.find( { ratings: { $elemMatch: { score: { $lte: 5 }, by: "anon" } } } )
Taking the predicates separately:分别使用谓词:
score: { $lte: 5 }
predicate are [ [ -Infinity, 5 ] ]
;score: { $lte: 5 }
谓词的边界是[ [ -Infinity, 5 ] ]
;by: "anon"
predicate are [ [ "anon", "anon" ] ]
.by: "anon"
谓词的边界是[ [ "anon", "anon" ] ]
。MongoDB can compound the two bounds to use the combined bounds of:MongoDB可以复合这两个边界以使用以下组合边界:
{ "ratings.score" : [ [ -Infinity, 5 ] ], "ratings.by" : [ [ "anon", "anon" ] ] }
$elemMatch
$elemMatch
的查询If the query does not join the conditions on the indexed array fields with 如果查询没有将索引数组字段上的条件与$elemMatch
, MongoDB cannot compound their bounds. $elemMatch
连接起来,MongoDB无法复合它们的边界。Consider the following query:考虑以下查询:
db.survey2.find( { "ratings.score": { $lte: 5 }, "ratings.by": "anon" } )
Because a single embedded document in the array does not need to meet both criteria, MongoDB does not compound the bounds. 因为数组中的单个嵌入文档不需要满足这两个条件,所以MongoDB不会复合边界。When using a compound index, if MongoDB cannot constrain all the fields of the index, MongoDB always constrains the leading field of the index, in this case 使用复合索引时,如果MongoDB无法约束索引的所有字段,MongoDB始终约束索引的前导字段,在本例中为"ratings.score"
:"ratings.score"
:
{ "ratings.score": [ [ -Infinity, 5 ] ], "ratings.by": [ [ MinKey, MaxKey ] ] }
$elemMatch
on Incomplete Path$elemMatch
If the query does not specify 如果查询未在嵌入字段的路径上指定$elemMatch
on the path of the embedded fields, up to but excluding the field names, MongoDB cannot compound the bounds of index keys from the same array.$elemMatch
,直到但不包括字段名,MongoDB无法复合来自同一数组的索引键的边界。
For example, a collection 例如,集合survey3
contains documents with a field item
and an array field ratings
:survey3
包含具有字段item
和数组字段ratings
的文档:
{ _id: 1, item: "ABC", ratings: [ { scores: [ { q1: 2, q2: 4 }, { q1: 3, q2: 8 } ], loc: "A" }, { scores: [ { q1: 2, q2: 5 } ], loc: "B" } ] } { _id: 2, item: "XYZ", ratings: [ { scores: [ { q1: 7 }, { q1: 2, q2: 8 } ], loc: "B" } ] }
Create a compound index on the 在ratings.scores.q1
and the ratings.scores.q2
fields:ratings.scores.q1
和ratings.scores.q2
字段上创建复合索引:
db.survey3.createIndex( { "ratings.scores.q1": 1, "ratings.scores.q2": 1 } )
The fields 字段"ratings.scores.q1"
and "ratings.scores.q2"
share the field path "ratings.scores"
and the $elemMatch
must be on that path."ratings.scores.q1"
和"ratings.scores.q2"
共享字段路径"ratings.scores"
,并且$elemMatch
必须位于该路径上。
The following query, however, uses an 但是,以下查询使用$elemMatch
but not on the required path:$elemMatch
,但不在所需路径上:
db.survey3.find( { ratings: { $elemMatch: { 'scores.q1': 2, 'scores.q2': 8 } } } )
As such, MongoDB cannot compound the bounds, and the 因此,MongoDB无法复合边界,"ratings.scores.q2"
field will be unconstrained during the index scan. "ratings.scores.q2"
字段在索引扫描期间将不受约束。To compound the bounds, the query must use 要复合边界,查询必须在路径$elemMatch
on the path "ratings.scores"
:"ratings.scores"
上使用$elemMatch
:
db.survey3.find( { 'ratings.scores': { $elemMatch: { 'q1': 2, 'q2': 8 } } } )