MongoDBでインデックスを作成する方法はいくつかあり、MongoDB 4.2から、ワイルドカードインデックスを作成できます。
ワイルドカードインデックスは、コレクション内の任意のフィールド、サブドキュメント、または配列に自動的に一致し、それらの一致にインデックスを付ける一種のフィルターと考えることができます。
これは、ドキュメントにさまざまな階層のさまざまなフィールドを持つ非構造化データが含まれている場合に役立ちます。このような場合、各ドキュメントにどのようなデータが含まれるかわからないため、インデックスがどうあるべきかを予測する方法はありません。
ワイルドカードインデックスは、フィールドのすべてのスカラー値にインデックスを付け、サブドキュメントまたは配列に自動的に再帰し、サブドキュメント/配列内のすべてのスカラーフィールドにインデックスを付けるため、このような非構造化データで役立ちます。
サンプルコレクション
ワイルドカードインデックスは、すべてのコレクションに対応しているわけではありません。異なる階層の異なるフィールドを持つ非構造化データを含むドキュメントを含む特定のコレクションに対してのみ、ワイルドカードインデックスを作成します。
以下は、pets
というコレクションの例です。 ワイルドカードインデックスの候補として適している可能性があります:
{
"_id" : 1,
"name" : "Wag",
"details" : {
"type" : "Dog",
"weight" : 20,
"awards" : {
"Florida Dog Awards" : "Top Dog",
"New York Marathon" : "Fastest Dog",
"Sumo 2020" : "Biggest Dog"
}
}
}
{
"_id" : 2,
"name" : "Fetch",
"details" : {
"born" : ISODate("2020-06-22T14:00:00Z"),
"color" : "Black"
}
}
{
"_id" : 3,
"name" : "Scratch",
"details" : {
"eats" : [
"Mouse Porridge",
"Bird Soup",
"Caviar"
],
"type" : "Cat",
"born" : ISODate("2020-12-19T14:00:00Z")
}
}
このコレクションの3つのドキュメントには、それぞれdetails
があります。 フィールドですが、そのフィールド内に異なるフィールドが含まれています。一貫性がありません。これにより、通常、各ドキュメントにどのフィールドが含まれるかわからないため、インデックスを作成するのが難しくなります。考えられるドキュメント構造を注意深く分析した後、おそらく複数のインデックスを作成する必要があります。
幸い、ワイルドカードインデックスを作成できます。
ただし、最初に、これらのフィールドの1つをクエリするときにクエリプランがどのように表示されるかを見てみましょう。ニューヨークマラソンで「最速の犬」賞を受賞した犬を見つけたいと想像してみてください。次のことができます:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } )
また、クエリプランを確認したい場合は、explain()
を追加できます。 最後まで:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()
これは次を返します:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "PetHotel.pets",
"indexFilterSet" : false,
"parsedQuery" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"queryHash" : "EC0D5185",
"planCacheKey" : "EC0D5185",
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"ok" : 1
}
これは、コレクションスキャン(COLLSCAN)を実行することを示しています。つまり、フィールドを探すためにすべてのドキュメントをスキャンする必要があります。
ワイルドカードインデックスを作成する
上記のコレクションのワイルドカードインデックスを作成する例を次に示します。
db.pets.createIndex({ "details.$**": 1 });
出力:
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
それでおしまい。ワイルドカードインデックスが作成されました。
ワイルドカードインデックスを作成するために、インデックスを作成するフィールド名(この場合はdetails
)を使用しました フィールド)、次にドット(.
)を追加しました )、そして重要な部分である$**
一部。
$**
このフィールドとそのすべてのサブドキュメントからワイルドカードインデックスを作成する必要があることを指定します。
$**
のプレフィックス details
ワイルドカードインデックスのスコープをdetails
のみに制限します フィールド。
次に、前述のクエリのクエリプランを再確認しましょう:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()
結果:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "PetHotel.pets",
"indexFilterSet" : false,
"parsedQuery" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"queryHash" : "EC0D5185",
"planCacheKey" : "7DFA23ED",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"$_path" : 1,
"details.awards.New York Marathon" : 1
},
"indexName" : "details.$**_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"$_path" : [ ],
"details.awards.New York Marathon" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"$_path" : [
"[\"details.awards.New York Marathon\", \"details.awards.New York Marathon\"]"
],
"details.awards.New York Marathon" : [
"[\"Fastest Dog\", \"Fastest Dog\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"ok" : 1
}
今回は、コレクションスキャン(COLLSCAN)が、新しく作成されたワイルドカードインデックスのインデックススキャン(IXSCAN)に置き換えられました。
details
内の各フィールド フィールドはパス/値としてインデックス付けされており、階層内のすべてのフィールドのインデックスにエントリがあります。フィールド値がサブドキュメントである場合(たとえば、awards
フィールド)、インデックス作成はサブドキュメントに降りてきて、プロセスを繰り返しました。
すべてのフィールドパスでのワイルドカードインデックスの作成
前の例では、単一のフィールドパスにワイルドカードインデックスを作成しました。 $**
を使用するだけで、すべてのフィールドパスにワイルドカードインデックスを作成できます。 接頭辞としてフィールドを付けずに。
たとえば、これを行うことができます:
db.pets.createIndex({ "$**": 1 });
これにより、すべてのフィールドパスにワイルドカードインデックスが作成されます。
実際、それは完全には真実ではありません。デフォルトでは、ワイルドカードインデックスは_id
に作成されません 分野。 _id
を含めるには フィールドの場合は、wildcardProjection
に含める必要があります ドキュメント。
ワイルドカードインデックスを作成できませんか?この設定を確認してください。
mongod
featureCompatibilityVersion
少なくとも4.2
である必要があります ワイルドカードインデックスを作成します。
この設定は、次のコードで確認できます。
db.adminCommand(
{
getParameter: 1,
featureCompatibilityVersion: 1
}
)
setFeatureCompatibilityVersion
を使用して設定できます コマンド:
db.adminCommand( { setFeatureCompatibilityVersion: "4.4" } )
setFeatureCompatibilityVersion
コマンドはadmin
で実行する必要があります データベース。