MongoDB でインデックスを適用する方法

MongoDB はドキュメント型データベースであるため、少し異なるインデックスが存在する。今回は RDB にはないインデックスの概念について見てみよう。

MongoDB のインデックス

MongoDB では基本的に、ドキュメントを作成するたびに _id 属性がユニークインデックスとして自動的に生成される。これで不足する場合は、独自に db.collection.createIndex() を使用してインデックスを作成する。db.collection.createIndex() によって作成されるインデックスは、B-tree データ構造のインデックスである。

MongoDB は単純なキー指定以外にも、いくつかのインデックス型をサポートする。具体的にサポートされるインデックス型は次のとおりである。

  • 単一キー
  • 複合キー
  • マルチキー
  • 地理空間
  • テキスト
  • ハッシュ

「複合キー」と「マルチキー」は名称が似ているが内容は異なる。「複合キー」は複数フィールドを組み合わせたキーであり、「マルチキー」は配列を扱う属性について、その配列に含まれるすべての値を対象にするキーである。

以下では、基本となる「単一キーインデックス」、「複合キーインデックス」、「マルチキーインデックス」について、具体的な使い方をサンプルコードで見ていく。

インデックスの基本作成

mongo シェルで次のコマンドを実行すると、指定したコレクションに対してインデックスを作成できる。

JavaScript コードでも関数は同じだが、3番目の引数にコールバックを指定できる点が異なる。

構文

db.collection.createIndex(keys, options)

引数

引数 Type 説明
keys string/object 値を持つフィールド名を指定する。昇順キーであれば 1、降順キーであれば -1 を指定する。
options object インデックス作成に関するオプションを指定する。オプションとして指定できるものには uniquecollation がある。他にもあるが、ここではこれだけ覚えておこう。

使用例

以下で「単一キーインデックス(Single field index)」、「複合キーインデックス(Compound index)」、「マルチキーインデックス(Multi-key index)」の使用例を見てみよう。

単一キーインデックスの作成

以下のようなサンプルドキュメントにインデックスを作成するサンプルコードを3つ扱う。MongoDB はドキュメント型データベースであるため、RDB にはない「埋め込みフィールド」や「埋め込みドキュメント」に対するインデックス作成ができる。

{
  "score": 1034,
  "location": { city: "Seoul", county: "Korea Republic of" }
}

単一フィールド

もっとも単純な「単一フィールド」に対するインデックス作成のサンプルコードである。

> db.collection.createIndex({ score: 1 })
> db.collection.find({ score: 1034 })
> db.collection.find({ score: { $gt: 1000 } })

埋め込みフィールド

MongoDB は属性値としてドキュメントを指定することもできる。このような場合、ドキュメント内のフィールド、つまりネストされた要素についてもインデックス化できる。

> db.collection.createIndex({ "location.city": 1 })
> db.collection.find({ "location.city": "Kyunggi" })

埋め込みドキュメント

上の「埋め込みフィールド」と似ているが、元のオブジェクトを指定することもできる。ただし、この場合は属性の数と属性の順序を含めて完全一致が求められる点に注意する必要がある。

> db.collection.createIndex({ location: 1 })
> db.collection.find({ city: "Seoul", county: "Korea Republic of" })

複合キーインデックスの作成

RDB にも存在する複合キーインデックスである。MongoDB では複数のフィールドをキーとして指定して作成できる。MongoDB の複合キーインデックスでは、「指定された複合キーすべてに一致する」パターンだけでなく、「一部に一致する」パターンでもインデックスが有効である。

次のサンプルデータに対して「複合キーインデックス」を作成する例を見てみよう。

{
  "item": "Apple",
  "location": "xxx store",
  "stock": 4,
  "type": "cases"
}
> db.collection.createIndex({ item: 1, location: 1, stock: 1 })
> db.collection.find({ item: "Apple" })
> db.collection.find({ item: "Apple", location: "xxx store" })
> db.collection.find({ item: "Apple", location: "xxx store", stock: { $gt: 0 } })

上の例ではインデックスの作成が item -> location -> stock であるため、その先頭部分である itemitem -> location などでもインデックスが有効になる。

マルチキーインデックスの作成

MongoDB には、配列を値として使用するフィールドもある。配列の値は「プリミティブ」でも「オブジェクト」でも、どちらの場合でも「マルチキーインデックス」を作成できる。

以下では、配列フィールド ratings を含むコレクションに対してインデックスを作成し、検索するサンプルを見てみる。

{ "item": "Apple",  ratings: [ 2, 9 ] }
{ "item": "Banana", ratings: [ 4, 3 ] }

インデックス作成は、単純に ratings に対して createIndex() を呼び出して作成できる。

> db.collection.createIndex({ ratings: 1 })

配列フィールドに対する検索は、通常 $elemMatch を使用する。以下の例では「3以上6以下の ratings が1レコード以上存在するドキュメント」を抽出している。

> db.collection.find({ ratings: { $elemMatch: { $gte: 3, $lte: 6 } } })
{ "_id" : ObjectId("5a2d24459c684f917e3ec0c2"), "item" : "XYZ", "ratings" : [ 4, 3 ] }

以下のように入力すると、「3以上または6以下を満たすレコードが1件以上存在するドキュメント」を抽出するため、結果的にすべて抽出されてしまう。

> db.collection.find({ ratings: { $gte: 3, $lte: 6 } })
{ "_id" : ObjectId("5a2d24399c684f917e3ec0c1"), "item" : "ABC", "ratings" : [ 2, 9 ] }
{ "_id" : ObjectId("5a2d24459c684f917e3ec0c2"), "item" : "XYZ", "ratings" : [ 4, 3 ] }

参考文書