Docs Menu
Docs Home
/
MongoDBマニュアル
/ / /

マルチキー インデックスの限界

項目一覧

  • マルチキー インデックスの限界の交差
  • 例: 限界の交差
  • $elemMatch を使用しないクエリ
  • マルチキー インデックスの複合限界
  • 例: 非配列フィールドと配列フィールドの複合限界
  • 例: 非配列フィールドと複数の配列フィールドの複合限界
  • 同じ配列の複数のフィールドの複合限界
  • 例: フィールドパスの相違に関する $elemMatch

インデックスの限界は、インデックスを使用してクエリを実行するときに MongoDB が検索するインデックス値の範囲を定義します。 インデックス付きフィールドに複数のクエリ述語を指定すると、MongoDB はそれらの述語の限界を組み合わせて、より小さな限界のインデックススキャンを生成しようとします。 インデックスの限界が小さいと、クエリが高速化され、リソース使用量が削減されます。

MongoDB は、 交差または複合限界を利用して限界を組み合わせます。

限界が交差されている点とは、複数の境界が重複する点を指します。 たとえば、限界が [ [ 3, Infinity ] ][ [ -Infinity, 6 ] ]の場合、これらの限界の交差は[ [ 3, 6 ] ]になります。

インデックス付き配列フィールドがある場合、配列に複数のクエリ述語を指定し、クエリを実行するためにマルチキー インデックスを使用するクエリを考えてみましょう。 MongoDB は$elemMatch演算子がクエリ述語に参加する場合、マルチキー インデックスの限界を交差できます。

次の例では、MongoDB が 限界交差 を使用して、クエリする値の範囲を小さくして、クエリのパフォーマンスを向上させる方法を示しています。

1

フィールドnameと配列フィールドgradesを持つドキュメントを含むstudentsコレクションを作成します。

db.students.insertMany(
[
{ _id: 1, name: "Shawn", grades: [ 70, 85 ] },
{ _id: 2, item: "Elena", grades: [ 92, 84 ] }
]
)
2

grades配列にマルチキー インデックスを作成します。

db.students.createIndex( { grades: 1 } )
3

次のクエリを実行します。

db.students.find( { grades : { $elemMatch: { $gte: 90, $lte: 99 } } } )

上記のクエリでは、 grades $elemMatchを使用して、指定された条件の両方に一致する要素が少なくとも 1 つ含まれているドキュメントを返します。

クエリ述語を個別に取得する

  • 90 以上の述語( $gte: 90 )の限界は[ [ 90, Infinity ] ]です。

  • 99 以下の述語( $lte: 99 )の限界は[ [ -Infinity, 99 ] ]です。

クエリでは$elemMatchを使用してこれらの述語を結合するため、MongoDB は次のように限界を交差します。

ratings: [ [ 90, 99 ] ]

クエリが配列フィールドの条件を$elemMatchと結合しない場合、MongoDB はマルチキー インデックスの限界を交差できません。

次のクエリを考えてみましょう。

db.students.find( { grades: { $gte: 90, $lte: 99 } } )

クエリは、 grades配列で次の内容を検索します。

  • 少なくとも 1 つの要素が 以上 90

  • 少なくとも 1 つの要素が 以下 99

同じ要素が両方の条件を満たすことができます。

上記のクエリでは$elemMatchが使用されていないため、MongoDB は境界を交差しません。 代わりに、MongoDB は次のいずれかの限界を使用します。

  • [ [ 90, Infinity ] ]

  • [ [ -Infinity, 99 ] ]

MongoDB は、2 つの限界のうちどちらを選択するかについて保証しません。

複合限界は、複合インデックスの複数のキーの限界を組み合わせます。 複数のキーの限界を使用すると、クエリの処理時間が短縮されます。MongoDB では各限界の結果を個別に計算する必要がないためです。

たとえば、次の限界を持つ複合インデックス{ temperature: 1, humidity: 1 }について考えてみます。

  • temperature の限界は[ [ 80, Infinity ] ]です。

  • humidity の限界は[ [ -Infinity, 20 ] ]です。

限界を複合化すると、両方の限界が使用されます。

{ temperature: [ [ 80, Infinity ] ], humidity: [ [ -Infinity, 20 ] ] }

MongoDB が 2 つの限界を複合化できない場合、MongoDB は先頭のフィールドの限界でインデックススキャンを制限します。 この例では、先頭のフィールドはtemperatureであり、制約はtemperature: [ [ 80, Infinity ] ]です。

次の例は、MongoDB が複合限界を使用してより効率的なクエリ制約を定義し、クエリのパフォーマンスを向上させる方法を示しています。

1

フィールドitemと配列フィールドratingsを持つドキュメントを含むsurveyコレクションを作成します。

db.survey.insertMany(
[
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] },
{ _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
]
)
2

フィールドと フィールドに 複合マルチキー インデックス を作成します。itemratings

db.survey.createIndex( { item: 1, ratings: 1 } )
3

次のクエリを実行します。

db.survey.find( { item: "XYZ", ratings: { $gte: 3 } } )

上記のクエリでは、インデックスの両方のキー( itemratings )に条件を指定しています。

述語を個別に取得する。

  • item: "XYZ"述語の限界は[ [ "XYZ", "XYZ" ]]です。

  • ratings: { $gte: 3 }述語の限界は[ [ 3, Infinity ] ]です。

MongoDB は、次の組み合わせた境界を使用します。

{ item: [ [ "XYZ", "XYZ" ] ], ratings: [ [ 3, Infinity ] ] }

次の例は、インデックスに配列以外のフィールドと複数の配列フィールドが含まれている場合に MongoDB が複合限界を使用する方法を示しています。

1

stringフィールド item と配列フィールド ratings を持つドキュメントを含む survey2 コレクションを作成します。

db.survey2.insertMany( [
{
_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" } ]
}
] )
2

次のフィールドに複合インデックスを作成します。

  • item (non-array)

  • ratings.score (配列)

  • ratings.by (配列)

db.survey2.createIndex(
{
"item": 1,
"ratings.score": 1,
"ratings.by": 1
}
)
3

次のクエリを実行します。

db.survey2.find(
{
item: "XYZ",
"ratings.score": { $lte: 5 },
"ratings.by": "anon"
}
)

述語を個別に取得する。

  • item: "XYZ"述語の限界は[ [ "XYZ", "XYZ" ] ]です。

  • score: { $lte: 5 }述語の限界は[ [ -Infinity, 5] ]です。

  • by: "anon"述語の限界は[ "anon", "anon" ]です。

MongoDB は、クエリ述語とインデックス キー値に応じて、 itemキーの限界を"ratings.score"の限界または"ratings.by"の限界と複合させます。 MongoDB では、 itemフィールドと複合化される限界は保証されません。

MongoDB は、次のいずれかの方法でクエリを実行します。

  • MongoDB はitemの限界と"ratings.score"の限界を複合化します。

    {
    "item" : [ [ "XYZ", "XYZ" ] ],
    "ratings.score" : [ [ -Infinity, 5 ] ],
    "ratings.by" : [ [ MinKey, MaxKey ] ]
    }
  • MongoDB はitemの限界と"ratings.by"の限界を複合化します。

    {
    "item" : [ [ "XYZ", "XYZ" ] ],
    "ratings.score" : [ [ MinKey, MaxKey ] ],
    "ratings.by" : [ [ "anon", "anon" ] ]
    }

"ratings.score"の限界と"ratings.by"の限界を複合するには、クエリは$elemMatchを使用する必要があります。

同じ配列のインデックス キーの限界を複合化するには、次の両方を満たす必要があります。

  • インデックス キーは、フィールド名まで同じフィールドパスを共有する必要があります。

  • クエリでは、そのパス上で$elemMatchを使用してフィールドに述語を指定する必要があります。

埋め込みドキュメント内のフィールドの場合、ドット付きフィールド名"a.b.c.d"など)はdのフィールドパスになります。 同じ配列のインデックス キーの限界を複合するには、 $elemMatchが までのパス上にあり、フィールド名自体を除外している必要があります(つまり"a.b.c" )。

次の例は、MongoDB が同じ配列のインデックス キーの限界を組み合わせる方法を示しています。この例では、前の例で使用した survey2 コレクションを使用しています。

1

フィールドと フィールドに複合インデックスを作成します。ratings.scoreratings.by

db.survey2.createIndex( { "ratings.score": 1, "ratings.by": 1 } )

フィールド"ratings.score""ratings.by"はフィールドパスratingsを共有しています。

2

次のクエリを実行します。

db.survey2.find( { ratings: { $elemMatch: { score: { $lte: 5 }, by: "anon" } } } )

上記のクエリでは、 ratingsフィールドで$elemMatchを使用して、両方の条件に一致する単一の要素が配列に少なくとも 1 つ含まれていることを要求します。

述語を個別に取得する。

  • score: { $lte: 5 }述語の限界は[ [ -Infinity, 5 ] ]です。

  • by: "anon"述語の限界は[ [ "anon", "anon" ] ]です。

MongoDB では、2 つの限界が次の限界に複合されています。

{ "ratings.score" : [ [ -Infinity, 5 ] ], "ratings.by" : [ [ "anon", "anon" ] ] }

クエリで共通パスから異なるフィールドに$elemMatchが指定されている場合、MongoDB は同じ配列のインデックス キーの限界を複合化できません

次の例は、フィールドパスの除算に関する$elemMatchを示しています。

1

コレクションsurvey3には、string フィールドitemと配列フィールドratingsを持つドキュメントが含まれます。

db.survey3.insertMany( [
{
_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" }
]
}
] )
2

フィールドと フィールドに複合インデックスを作成します。ratings.scores.q1ratings.scores.q2

db.survey3.createIndex( { "ratings.scores.q1": 1, "ratings.scores.q2": 1 } )

フィールド"ratings.scores.q1""ratings.scores.q2"はフィールドパス"ratings.scores"を共有しています。 複合インデックスの限界を設定するには、クエリは共通フィールドパスで$elemMatchを使用する必要があります。

3

次のクエリでは、必要なパスにない$elemMatchを使用します。

db.survey3.find( { ratings: { $elemMatch: { 'scores.q1': 2, 'scores.q2': 8 } } } )

MongoDB はインデックスの限界を複合化することはできず、インデックス スキャン中に"ratings.scores.q2"フィールドは制約されません。

限界を複合するには、クエリが共通パス"ratings.scores"$elemMatchを使用する必要があります。

db.survey3.find( { 'ratings.scores': { $elemMatch: { 'q1': 2, 'q2': 8 } } } )

戻る

埋め込み配列フィールド