Multikey Indexes
項目一覧
マルチキー インデックスは、配列値を含むフィールドからデータを収集してソートします。マルチキー インデックスにより、配列フィールドに対するクエリのパフォーマンスが向上します。
マルチキーのタイプを明示的に指定する必要はありません。配列値を含むフィールドにインデックスを作成すると、MongoDB では自動的にそのインデックスがマルチキー インデックスに設定されます。
MongoDB では、スカラー値(文字列や数値など)と埋め込みドキュメントの両方を含む配列に対してマルチキー インデックスを作成できます。配列に同じ値のインスタンスが複数含まれている場合、インデックスには値のエントリが 1 つだけ含まれます。
マルチキー インデックスを作成するには、次のプロトタイプを使用します。
db.<collection>.createIndex( { <arrayField>: <sortOrder> } )
この画像は、 addr.zip
フィールドのマルチキー インデックスを示しています。
MongoDB Atlas でホストされる配置用UIに複合インデックスを作成・管理できます。
ユースケース
アプリケーションが配列値を含むフィールドを頻繁にクエリする場合は、マルチキー インデックスを使用するとクエリのパフォーマンスが向上します。
よくクエリされるフィールドにインデックスを作成すると、それらのクエリを対象とする可能性が高くなります。対象のクエリとは、ドキュメントを検査することなく、インデックスを使用して完全に満たすことができるクエリです。これにより、クエリのパフォーマンスが最適化されます。
たとえば、 students
コレクション内のドキュメントには、学生が学期を通して取得したテストのスコアの配列であるtest_scores
フィールドが含まれています。上位の生徒、つまり少なくとも 5 つのtest_scores
が 90
よりも大きい生徒のリストが定期的に更新されます。
test_scores
フィールドにインデックスを作成すると、このクエリのパフォーマンスを向上させることができます。test_scores
には配列値が含まれているため、MongoDB はインデックスをマルチキー インデックスとして格納します。
はじめる
マルチキー インデックスを作成するには、以下を参照してください。
詳細
このセクションでは、マルチキー インデックスの技術的詳細と制限について説明します。
インデックスの限界
インデックス スキャンの限界は、クエリ中に検索するインデックスの部分を定義します。マルチキー インデックスの限界の計算は特別なルールに従います。詳細については、「マルチキー インデックスの限界」を参照してください。
Unique Multikey Indexes
ユニークなマルチキー インデックスでは、そのドキュメントのインデックスキー値が別のドキュメントのインデックスキー値と重複しない限り、インデックスキー値が繰り返される配列要素がドキュメントに含まれる場合があります。
この動作の詳細と例については、「複数の別個のドキュメント間での一意制約」を参照してください。
複合マルチキー インデックス
複合マルチキー インデックスでは、インデックス作成されたそれぞれのドキュメントに、値が配列であるインデックス付きフィールドを最大で 1 つ含めることができます。具体的な説明は以下の通りです。
インデックス仕様内の複数のフィールドが配列の場合、複合マルチキー インデックスを作成することはできません。例ば、このドキュメントを含むコレクションを考えてみます。
{ _id: 1, scores_spring: [ 8, 6 ], scores_fall: [ 5, 9 ] } 複合マルチキー インデックス
{ scores_spring: 1, scores_fall: 1 }
はインデックス内の両方のフィールドが配列であるため、作成できません。複合マルチキー インデックスがすでに存在する場合、この制限に違反するドキュメントを挿入することはできません。
これらのドキュメントを含むコレクションを考えてみます。
{ _id: 1, scores_spring: [8, 6], scores_fall: 9 } { _id: 2, scores_spring: 6, scores_fall: [5, 7] } 複合マルチキー インデックス
{ scores_spring: 1, scores_fall: 1 }
を作成できるのは、各ドキュメントで、複合マルチキー インデックスでインデックス付けされた 1 つのフィールドのみが配列であるためです。scores_spring
フィールドとscores_fall
フィールドの両方の配列値を含むドキュメントはありません。ただし、複合マルチキー インデックスの作成後、
scores_spring
フィールドとscores_fall
フィールドの両方が配列であるドキュメントを挿入しようとすると、挿入は失敗します。
ソート
マルチキー インデックスでインデックスされた配列フィールドに基づいてソートする場合、次の両方が当てはまらない限り、クエリプランにはブロッキングソートステージが含まれます。
すべてのソートフィールドのインデックスの限界は
[MinKey, MaxKey]
です。マルチキー インデックスの付いたフィールドの境界には、ソート パターンと同じパス プレフィックスはありません。
シャードキー
マルチキー インデックスをシャードキー インデックスとして指定することはできません。
ただし、シャードキー インデックスが複合インデックスのプレフィックスである場合、末尾のキー(シャードキーには含まれない)のいずれかが配列にインデックスを付けると、複合インデックスが複合マルチキー インデックスになる場合があります。
ハッシュされたインデックス
ハッシュされたインデックスをマルチキーにすることはできません。
カバード クエリ
次の条件が満たされている場合、マルチキー インデックスはクエリをカバーできます。
クエリは配列フィールドを返しません(つまり、配列はクエリプロジェクションに含まれていません)。つまり、クエリをカバーするには、マルチキー インデックスが複合である必要があります。
クエリには
$elemMatch
が含まれていません。このクエリは、対象となる他のすべてのクエリ要件を満たしています。
たとえば、以下のドキュメントのあるmatches
コレクションを考えます。
db.matches.insertMany( [ { name: "Joe", event: [ "open", "tournament" ] }, { name: "Bill", event: [ "match", "championship" ] } ] )
matches
コレクションでは、 event
フィールドとname
フィールドに複合マルチキー インデックスがあります。
db.matches.createIndex( { event: 1, name: 1 } )
event
フィールドに配列値が含まれているため、上記のインデックスはマルチキーです。
インデックスは次のクエリをカバーします。
db.matches.find( { event: 'championship' }, { _id: 0, name: 1 } ) db.matches.find( { name: 'Bill', event: 'championship' }, { _id: 0, name: 1 } )
プロジェクションには event
配列フィールドが含まれているため、インデックスは次のクエリをカバーしていません。
db.matches.find( { event: 'championship' }, { _id: 0, event: 1 } )
配列フィールド全体に対するクエリ
クエリ フィルターで配列全体の完全一致が指定されている場合、MongoDB はマルチキー インデックスを使用してクエリ配列の最初の要素を検索できますが、マルチキー インデックス スキャンを使用して配列全体を検索することはできません。
代わりに、マルチキー インデックスを使用してクエリ配列の最初の要素を検索した後、MongoDB は関連するドキュメントを取得し、配列がクエリの配列と一致するドキュメントをフィルタリングします。
たとえば、次のドキュメントを含むinventory
コレクションを考えます。
db.inventory.insertMany( [ { _id: 5, type: "food", item: "apple", ratings: [ 5, 8, 9 ] } { _id: 6, type: "food", item: "banana", ratings: [ 5, 9 ] } { _id: 7, type: "food", item: "chocolate", ratings: [ 9, 5, 8 ] } { _id: 8, type: "food", item: "fish", ratings: [ 9, 5 ] } { _id: 9, type: "food", item: "grapes", ratings: [ 5, 9, 5 ] } ] )
inventory
コレクションでは、 ratings
フィールドにマルチキー インデックスがあります。
db.inventory.createIndex( { ratings: 1 } )
次のクエリは、 ratings
フィールドが配列[ 5, 9 ]
であるドキュメントを検索します。
db.inventory.find( { ratings: [ 5, 9 ] } )
MongoDB ではマルチキー インデックスを使用して、 ratings
配列内の任意の位置に5
を持つドキュメントを見つけることができます。次に、MongoDB でこれらのドキュメントが取得され、ratings
配列がクエリ配列 [ 5, 9 ]
と等しいドキュメントがフィルタリングされます。
$expr
$expr
演算子はマルチキー インデックスをサポートしていません。
詳細
MongoDB でマルチキー インデックスの限界を組み合わせてパフォーマンスを向上させる方法については、「マルチキー インデックスの限界」を参照してください。
配列フィールドをクエリする方法については、以下を参照してください。