- Indexes >
- Index Concepts >
- Multikey Index Bounds
Multikey Index Bounds¶
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.
Intersect Bounds for Multikey Index¶
Bounds intersection refers to a logical conjunction (i.e. AND
) of
multiple bounds. For instance, given two bounds [ [ 3, Infinity ] ]
and [ [ -Infinity, 6 ] ]
, the intersection of the bounds results in
[ [ 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.
For example, a collection survey
contains documents with a field
item
and an array field ratings
:
Create a multikey index on the ratings
array:
The following query uses $elemMatch
to require that the array
contains at least one single element that matches both conditions:
Taking the predicates separately:
- the bounds for the greater than or equal to 3 predicate (i.e.
$gte: 3
) are[ [ 3, Infinity ] ]
; - the bounds for the less than or equal to 6 predicate (i.e.
$lte: 6
) are[ [ -Infinity, 6 ] ]
.
Because the query uses $elemMatch
to join these predicates,
MongoDB can intersect the bounds to:
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:
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. Because a single element does not need to meet both criteria,
MongoDB does not intersect the bounds and uses either [ [ 3,
Infinity ] ]
or [ [ -Infinity, 6 ] ]
. MongoDB makes no guarantee
as to which of these two bounds it chooses.
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:
If MongoDB cannot compound the two bounds, MongoDB always constrains
the index scan by the bound on its leading field, in this case, 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, a collection survey
contains documents with a field
item
and an array field ratings
:
Create a compound index on the item
field and the ratings
field:
The following query specifies a condition on both keys of the index:
Taking the predicates separately:
- the bounds for the
item: "XYZ"
predicate are[ [ "XYZ", "XYZ" ] ]
; - the bounds for the
ratings: { $gte: 3 }
predicate are[ [ 3, Infinity ] ]
.
MongoDB can compound the two bounds to use the combined bounds of:
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:
The dotted field name for the score
field is "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
:
Create a compound index on the non-array
field item
as well as two fields from an array ratings.score
and
ratings.by
:
The following query specifies a condition on all three fields:
Taking the predicates separately:
- the bounds for the
item: "XYZ"
predicate are[ [ "XYZ", "XYZ" ] ]
; - the bounds for the
score: { $lte: 5 }
predicate are[ [ -Infinity, 5 ] ]
; - the bounds for the
by: "anon"
predicate are[ "anon", "anon" ]
.
MongoDB can compound the bounds for the 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. MongoDB
makes no guarantee as to which bounds it compounds with the item
field. For instance, MongoDB will either choose to compound the
item
bounds with the "ratings.score"
bounds:
Or, MongoDB may choose to compound the item
bounds with
"ratings.by"
bounds:
However, to compound the bounds for "ratings.score"
with the bounds
for "ratings.by"
, the query must use $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.
For a field in an embedded document, the dotted field name, such as "a.b.c.d"
, is the field path for
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"
.
For instance, create a compound index on
the ratings.score
and the ratings.by
fields:
The fields "ratings.score"
and "ratings.by"
share the field
path 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:
Taking the predicates separately:
- the bounds for the
score: { $lte: 5 }
predicate is[ -Infinity, 5 ]
; - the bounds for the
by: "anon"
predicate is[ "anon", "anon" ]
.
MongoDB can compound the two bounds to use the combined bounds of:
Query Without $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:
Because a single embedded document in the array does not need to meet
both criteria, MongoDB does not compound the bounds. 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 "ratings.score"
:
$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.
For example, a collection survey3
contains documents with a field
item
and an array field ratings
:
Create a compound index on the
ratings.score.q1
and the ratings.score.q2
fields:
The fields "ratings.score.q1"
and "ratings.score.q2"
share the
field path "ratings.score"
and the $elemMatch
must be on
that path.
The following query, however, uses an $elemMatch
but not on
the required path:
As such, MongoDB cannot compound the bounds, and the
"ratings.score.q2"
field will be unconstrained during the index
scan. To compound the bounds, the query must use $elemMatch
on
the path "ratings.score"
:
Compound $elemMatch
Clauses¶
Consider a query that contains multiple $elemMatch
clauses on
different field paths, for instance, "a.b": { $elemMatch: ... },
"a.c": { $elemMatch: ... }
. MongoDB cannot combine the bounds of the
"a.b"
with the bounds of "a.c"
since "a.b"
and "a.c"
also require $elemMatch
on the path a
.
For example, a collection survey4
contains documents with a field
item
and an array field ratings
:
Create a compound index on the
ratings.score.q1
and the ratings.score.q2
fields:
Consider the following query with two $elemMatch
clauses:
Taking the predicates separately:
the bounds for the
"ratings.score"
predicate are the compound bounds:the bounds for the
"ratings.certainty"
predicate are the compound bounds:
However, MongoDB cannot compound the bounds for "ratings.score"
and
"ratings.certainty"
since $elemMatch
does not join the
two. Instead, MongoDB constrains the leading field of the index
"ratings.score.q1"
which can be compounded with the bounds for
"ratings.score.q2"
: