mongodbを使ってみる (4) - インデックスに関して (2) -
引き続きMongoDBのインデックスに関してドキュメント読みつつ進めてまいる
で大体のインデックスを作るのは前回でやったわけなんだが、いわゆるインデックスにもUNIQUEインデックスだったりで存在するという事でやってみた
まずその前に、MongoDBとかそういう系のKVSっていうのは基本的にスキーマレスである前提が存在すると思うのですが、UNIQUEインデックスを後で付けたら付けたで問題になるんじゃねーかなって思う所なので。でそれをサポートする為にdropDupsっていうオプションがあり、UNIQUEインデックスを保証させる際に既に重複している部分は削除するような仕組みがある模様。でもデータ消されたらたまったもんじゃねーってオチにならないかなーって思うので、とりあえず自分の無い頭で考えた所
- db.createCollectionで事前にコレクションは作っておく
- db.コレクション名.ensureIndexでUNIQUEインデックス作っておく
な感じの方式採用すれば良いんじゃねーかなと。あくまでUNIQUEであるべきインデックスをつける場合のみこういう手法採用する方が良いんじゃないかと。まぁそれを踏まえてやってみると
// samplesコレクションを作る
db.createCollection("samples")
// nameに対してUNIQUEインデックスを作っておく
db.samples.ensureIndex({ name: 1 }, { unique: true })
// 更にtypeに対してインデックスを作っておく
db.samples.ensureIndex({ type: 1 })
// データを突っ込む
db.samples.save({ name: "hoge", type: 1 })
db.samples.save({ name: "fuga", type: 1 })
// ここまではオッケー
db.samples.find()
db.samples.save({ name: "hoge", type: 1 })
// E11000 duplicate key error index: sample.samples.$name_1 dup key: { : "hoge" } なエラーになる
的な感じな。うまいことそこら辺な設計はちゃんとしないとあとで痛い目にあいそうな気もしなくはないので
でdropDupsも一応検証してみますかという事で
db.samples.save({ name: "hoge", type: 1 })
db.samples.save({ name: "hoge", type: 1 })
db.samples.find()
出力が
{ "_id" : ObjectId("50f4e59abc3d8a4279742235"), "name" : "hoge", "type" : 1 }
{ "_id" : ObjectId("50f4e5a2bc3d8a4279742236"), "name" : "hoge", "type" : 1 }
同じデータを突っ込んでおく。でこの状態でnameにUNIQUEインデックスをつけると
E11000 duplicate key error index: sample.samples.$name_1 dup key: { : "hoge" }
という風に上記でも書いたけど、今回は既にデータがある状態でインデックスをつけるとエラーになる。んじゃdropDupsをすると
db.samples.ensureIndex({ name: 1 }, { unique: true, dropDups: true })
db.samples.find()
// { "_id" : ObjectId("50f4e59abc3d8a4279742235"), "name" : "hoge", "type" : 1 }
という感じで2回目にsaveしたのがなくなっとるっていうオチになる。まぁこういう自体になるのは場合によっては非常にやばげな事だと思うので
んまぁ個人的な意見ですが、UNIQUEインデックスを確保する必要のあるケースでは事前設計が重要かもって所
追記
DBに存在するインデックスを確認したい場合は
db.system.indexes.find()
をすれば良い。ただコレクション毎に出したいのであればnsキーをフィルターすれば良いので
// sampleデータベース中のsamplesコレクション -> sample.samples
db.system.indexes.find({ ns: "sample.samples" })