前回 基本的な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 に関するエントリーはおわり。