ボクココ

個人開発に関するテックブログ

MongoDB の Index 入門その2

前回 基本的なIndexの貼り方を紹介したので、引き続きMongoDB関連のエントリー。

今回はドキュメント内に配列や Embed Documentがあった場合。

Embed Document

ご存知の通り、MongoDBはドキュメント内にドキュメントをさらに書ける。

{
  "name" : "hoge",
  "loc": {
    "city" : "Tokyo",
    "country" : "Japan"
  }
}

さて、ここで Tokyoをwhereでクエリを発行した場合,

db.test.ensureIndex({"loc.city": 1})

とする必要がある。 ({"loc": 1}) は、Embed Document内の全ての要素を検索条件として指定した場合のみ有効となる。こういうケースはあんま無いだろうから、基本使わないと思う。

配列

Embed Documentとほとんど考え方は同じ。

db.test.ensureIndex({"comments.date": 1})

こうすると配列の要素の一つずつにindexが付与される。Embed Documentの例のように、({"comments": 1}) と全体をくくることはできないので注意。

あと複数indexを作成する場合、配列のindexは一つである必要がある。indexの数が爆発しないようにMongoDBが制御しているからだそうだ。

配列を含むindexが1つでもあれば、それは multikey index とされる。これは クエリを投げた後に.explain()をチェインすることでわかる。これは普通のindexよりちょっと遅い。一回作っちゃったらそれは消してindexを再生成する必要がある。

indexを使わないとき?

コレクションのうち、30%以上のデータを返すようなパターンが頻繁に起きる場合はテーブルスキャンのほうがいい場合が多い。バッチ処理とかエクスポートして何かする専用のクエリのときとか。

Sparse Indexes

index でユニークをtrueにすると、重複データを入れられなくするようにすることができる。

db.test.ensureIndex({"loc.city": 1}, {"unique" : true})

これは例えば一個 null のデータが入っていたとして、さらに null のデータを入れようとした場合でも例外が発生してしまう。だけど"データがあるときだけユニークにしたい"というケースがあるはず。そんなときに使うのがSparse Index.

db.test.ensureIndex({"loc.city": 1}, {"unique" : true, "sparse" : true})

この場合、 find()で検索したときにそのindexを使った検索結果には表示されないことに注意。例えばxにsparse indexがあった場合のこんなクエリ

db.test.find({"x" : {"$ne" : 2}})

結果はnullの入っているxは結果が返ってこなくなる。

indexの確認

色々indexを作ってきて今までのを確認したい: db.test.getIndexes()

index名を変えたい: db.test.ensureIndex({...}, {"name": "hoge"} これは大量のフィールドに対してindexを貼った場合にindex名のリミットにかからないようにするといった場合には有効。

indexを変えたい: db.test.dropIndex("index name")

MongoDB の index に関するエントリーはおわり。