sql >> データベース >  >> NoSQL >> MongoDB

MongoDBでワイルドカードインデックスを作成する

    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で実行する必要があります データベース。


    1. 配列内の配列へのMongoプッシュ

    2. ベンダーロックインなしのMongoDB4.2管理と監視

    3. ServiceStack:サービスを手動で呼び出すときにパイプラインを復元しますか?

    4. MongoDB-配列内のオブジェクトを更新または挿入します