Docs Home → Develop Applications → MongoDB Manual
Multikey Index Bounds多键索引边界
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将尝试通过交集或复合来组合这些谓词的边界,以便生成具有较小边界的扫描。
Intersect Bounds for Multikey Index多键索引的交界
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, create a 例如,创建一个survey
collection that contains documents with a field item
and an array field ratings
:survey
集合,其中包含具有字段item
和数组字段ratings
的文档:
db.survey.insertMany(
[
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] },
{ _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
]
)
Create a multikey index on the 在ratings
array:ratings
数组上创建一个多键索引:
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:将谓词分开:
the bounds for the greater than or equal to 3 predicate (i.e.大于或等于$gte:3
) are[ [ 3, Infinity ] ]
;3
的谓词(即$gte:3
)的边界为[ [ 3, Infinity ] ]
;the bounds for the less than or equal to 6 predicate (i.e.小于或等于$lte:6
) are[ [ -Infinity, 6 ] ]
.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. $elemMatch
联接数组字段上的条件,MongoDB将无法与多键索引边界相交。Consider the following query:请考虑以下查询:
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不能保证它选择这两个边界中的哪一个。
Compound Bounds for Multikey Index多键索引的复合边界
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 ] ]
。
Compound Index on an Array Field数组字段上的复合索引
Consider a compound multikey index; i.e. a compound index where one of the indexed fields is an array. 考虑一个复合多键索引;即一个复合索引,其中一个索引字段是数组。For example, create a 例如,创建一个survey
collection that contains documents with a field item
and an array field ratings
:survey
集合,其中包含具有字段item
和数组字段ratings
的文档:
db.survey.insertMany(
[
{ _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:将谓词分开:
the bounds for theitem: "XYZ"
predicate are[ [ "XYZ", "XYZ" ] ]
;item: "XYZ"
的界限的谓词为[ [ "XYZ", "XYZ" ] ]
;the bounds for theratings: { $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 ] ] }
Range Queries on a Scalar Indexed Field (WiredTiger)标量索引字段的范围查询(WiredTiger)
For the WiredTiger and In-Memory storage engines only,仅对于WiredTiger和In-Memory存储引擎,
In multikey index, MongoDB keeps track of which indexed field or fields cause an index to be a multikey index. 在多键索引中,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, MongoDB will intersect the bounds for the field.对于WiredTiger和In-Memory存储引擎,如果查询操作在复合多键索引的索引标量字段上指定了多个谓词,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" ] ]
和ratings
到[[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, create a 例如,创建一个包含以下文档的survey
collection that contains the following documents:survey
集合:
db.survey.insertMany(
[
{ _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 不是标量字段。 |
Compound Index on Fields from an Array of Embedded Documents嵌入文档数组中字段的复合索引
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
字段的虚线字段名称为"ratings.score"
。
Compound Bounds of Non-array Field and Field from an Array非数组字段与数组字段的复合边界
Consider a collection 考虑集合survey2
contains documents with a field item
and an array field ratings
:survey2
包含具有字段item
和数组字段item
的文档:
{
_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:将谓词分开:
the bounds for theitem: "XYZ"
predicate are[ [ "XYZ", "XYZ" ] ]
;item: "XYZ"
的界限的谓词为[ [ "XYZ", "XYZ" ] ]
;the bounds for thescore: { $lte: 5 }
predicate are[ [ -Infinity, 5 ] ]
;score: { $lte: 5 }
谓词的边界是[ [ -Infinity, 5 ] ]
;the bounds for theby: "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.有关详细信息,请参阅数组中索引字段的复合边界。
Compound Bounds of Index Fields from an Array数组中索引字段的复合边界
To compound together the bounds for index keys from the same array:要将同一数组中索引键的边界组合在一起,请执行以下操作:
the index keys must share the same field path up to but excluding the field names, and索引键必须共享相同的字段路径,直到但不包括字段名,以及the query must specify predicates on the fields using查询必须在该路径上使用$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"
共享字段路径ratings
。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:将谓词分开:
the bounds for thescore: { $lte: 5 }
predicate are[ [ -Infinity, 5 ] ]
;score: { $lte: 5 }
谓词的边界是[ [ -Infinity, 5 ] ]
;the bounds for theby: "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" ] ] }
Query Without $elemMatch
不带$elemMatch
的查询
$elemMatch
If the query does not join the conditions on the indexed array fields with 如果查询没有使用$elemMatch
, MongoDB cannot compound their bounds. Consider the following query:$elemMatch
联接索引数组字段上的条件,MongoDB就无法复合它们的边界。请考虑以下查询:
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
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 } } } )