特徴
・BSON(JSONをバイナリ化)形式で保存したものをvalueとして、特定のkeyに紐づける
・ドキュメントデータベース(スキーマレス、カラムが固定されない)
(テーブルのことをコレクション、レコードのことをドキュメントと呼ぶ)
・JOINと似たような機能のembedという機構が存在する
・高速、かつドライバが豊富に用意されている
インストールと操作方法
root@akat:/home/akat# aptitude install mongodb root@akat:/home/akat# mongo # mongoシェルの起動 MongoDB shell version: 2.0.6 connecting to: test > help db.help() help on db methods db.mycoll.help() help on collection methods rs.help() help on replica set methods help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of log in memory, 'global' is default use <db_name> set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell > show dbs # dbの表示 local (empty) test 0.203125GB > db.local.save({name:"akatuki"}) # dbへの登録 > db.local.find() { "_id" : ObjectId("52e7ceb6c54ecea55b6be1b7"), "name" : "akatuki" } # _idというユニークな値を持っている > use blog_app; # useでDBができたように見えるが、コレクションやドキュメントを登録するまでは認識されない switched to db blog_app > show dbs; local (empty) test 0.203125GB > db.createCollection("posts") # コレクションを作成する { "ok" : 1 } > show dbs; blog_app 0.203125GB local (empty) test 0.203125GB > db.help # 利用できる関数を表示する function () { print("DB methods:"); print("\tdb.addUser(username, password[, readOnly=false])"); print("\tdb.auth(username, password)"); print("\tdb.cloneDatabase(fromhost)"); print("\tdb.commandHelp(name) returns the help for the command"); print("\tdb.copyDatabase(fromdb, todb, fromhost)"); print("\tdb.createCollection(name, { size : ..., capped : ..., max : ... } )"); print("\tdb.currentOp() displays the current operation in the db"); # 長いので省略 > db.stats(); # DBの状態を表示 { "db" : "blog_app", "collections" : 3, "objects" : 4, "avgObjSize" : 58, "dataSize" : 232, "storageSize" : 20480, "numExtents" : 3, "indexes" : 1, "indexSize" : 8176, "fileSize" : 201326592, "nsSizeMB" : 16, "ok" : 1 } > db.dropDatabase(); # DBの削除 { "dropped" : "blog_app", "ok" : 1 } > use blog_app; # 再度blog_appを作成 switched to db blog_app > db.createCollection("posts"); # コレクションを作成 { "ok" : 1 } > db.createCollection("users"); { "ok" : 1 } > show collections; posts system.indexes users > db.users.drop(); # usersを削除 true > db.posts.renameCollection("entries"); # 名前を変更する { "ok" : 1 } > show collections; entries system.indexes > db.entries.insert({"name":"akat","email":"akat@gmail.com"}); # コレクションにinsertする > db.entries.find(); { "_id" : ObjectId("530045ff860d11e5c1173c77"), "name" : "akat", "email" : "akat@gmail.com" } > db.entries.insert({"name":"akatuki","lang":["JP","US"]}); > db.entries.find(); # ドキュメントを表示する { "_id" : ObjectId("530045ff860d11e5c1173c77"), "name" : "akat", "email" : "akat@gmail.com" } { "_id" : ObjectId("53004634860d11e5c1173c78"), "name" : "akatuki", "lang" : [ "JP", "US" ] } > db.entries.remove(); # ドキュメントを削除する > db.entries.find(); > for (var i=0;i<10;i++){ ... db.users.insert( ... {"name":"user-"+i, ... "team":i %3, ... "score":Math.floor(Math.random()*100) ... } ... ); ... } # JavaScriptを利用することが可能 > db.users.find() { "_id" : ObjectId("53004852860d11e5c1173c83"), "name" : "user-0", "team" : 0, "score" : 28 } { "_id" : ObjectId("53004852860d11e5c1173c84"), "name" : "user-1", "team" : 1, "score" : 24 } { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } { "_id" : ObjectId("53004852860d11e5c1173c86"), "name" : "user-3", "team" : 0, "score" : 40 } { "_id" : ObjectId("53004852860d11e5c1173c87"), "name" : "user-4", "team" : 1, "score" : 33 } { "_id" : ObjectId("53004852860d11e5c1173c88"), "name" : "user-5", "team" : 2, "score" : 72 } { "_id" : ObjectId("53004852860d11e5c1173c89"), "name" : "user-6", "team" : 0, "score" : 19 } { "_id" : ObjectId("53004852860d11e5c1173c8a"), "name" : "user-7", "team" : 1, "score" : 46 } { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 61 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "name" : "user-9", "team" : 0, "score" : 40 } > db.users.find({"team":0}); # teamが0であるものを抽出 { "_id" : ObjectId("53004852860d11e5c1173c83"), "name" : "user-0", "team" : 0, "score" : 28 } { "_id" : ObjectId("53004852860d11e5c1173c86"), "name" : "user-3", "team" : 0, "score" : 40 } { "_id" : ObjectId("53004852860d11e5c1173c89"), "name" : "user-6", "team" : 0, "score" : 19 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "name" : "user-9", "team" : 0, "score" : 40 } > db.users.find({"team":0},{"name":true}); # teamが0であるもので、nameだけ抽出 { "_id" : ObjectId("53004852860d11e5c1173c83"), "name" : "user-0" } { "_id" : ObjectId("53004852860d11e5c1173c86"), "name" : "user-3" } { "_id" : ObjectId("53004852860d11e5c1173c89"), "name" : "user-6" } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "name" : "user-9" } > db.users.find({"team":{$ne:0}}); # teamが0でないものを抽出 { "_id" : ObjectId("53004852860d11e5c1173c84"), "name" : "user-1", "team" : 1, "score" : 24 } { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } { "_id" : ObjectId("53004852860d11e5c1173c87"), "name" : "user-4", "team" : 1, "score" : 33 } { "_id" : ObjectId("53004852860d11e5c1173c88"), "name" : "user-5", "team" : 2, "score" : 72 } { "_id" : ObjectId("53004852860d11e5c1173c8a"), "name" : "user-7", "team" : 1, "score" : 46 } { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 61 } > db.users.find({"score":{$gt:40}}); # scoreが40より大きいものを抽出(以上のときは$gte) { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } { "_id" : ObjectId("53004852860d11e5c1173c88"), "name" : "user-5", "team" : 2, "score" : 72 } { "_id" : ObjectId("53004852860d11e5c1173c8a"), "name" : "user-7", "team" : 1, "score" : 46 } { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 61 } > db.users.find({"score":{$gt:40,$lt:60}}); # scoreが40より大きく、60未満を抽出 { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } { "_id" : ObjectId("53004852860d11e5c1173c8a"), "name" : "user-7", "team" : 1, "score" : 46 } > db.users.find({"name":{$regex:/user-[0-2]/i}}); # 正規表現にて抽出 { "_id" : ObjectId("53004852860d11e5c1173c83"), "name" : "user-0", "team" : 0, "score" : 28 } { "_id" : ObjectId("53004852860d11e5c1173c84"), "name" : "user-1", "team" : 1, "score" : 24 } { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } > db.users.find().sort({"score":1}) # scoreについて昇順に並べる(降順は-1) { "_id" : ObjectId("53004852860d11e5c1173c89"), "name" : "user-6", "team" : 0, "score" : 19 } { "_id" : ObjectId("53004852860d11e5c1173c84"), "name" : "user-1", "team" : 1, "score" : 24 } { "_id" : ObjectId("53004852860d11e5c1173c83"), "name" : "user-0", "team" : 0, "score" : 28 } { "_id" : ObjectId("53004852860d11e5c1173c87"), "name" : "user-4", "team" : 1, "score" : 33 } { "_id" : ObjectId("53004852860d11e5c1173c86"), "name" : "user-3", "team" : 0, "score" : 40 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "name" : "user-9", "team" : 0, "score" : 40 } { "_id" : ObjectId("53004852860d11e5c1173c8a"), "name" : "user-7", "team" : 1, "score" : 46 } { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 61 } { "_id" : ObjectId("53004852860d11e5c1173c88"), "name" : "user-5", "team" : 2, "score" : 72 } > db.users.find().limit(3) # 3件抽出 { "_id" : ObjectId("53004852860d11e5c1173c83"), "name" : "user-0", "team" : 0, "score" : 28 } { "_id" : ObjectId("53004852860d11e5c1173c84"), "name" : "user-1", "team" : 1, "score" : 24 } { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } > db.users.find().skip(2).limit(3) # 2件飛ばして、3件抽出 { "_id" : ObjectId("53004852860d11e5c1173c85"), "name" : "user-2", "team" : 2, "score" : 51 } { "_id" : ObjectId("53004852860d11e5c1173c86"), "name" : "user-3", "team" : 0, "score" : 40 } { "_id" : ObjectId("53004852860d11e5c1173c87"), "name" : "user-4", "team" : 1, "score" : 33 } > db.users.find().count() # ドキュメント数を抽出 10 > db.users.distinct("team") # ユニークな値を抽出 [ 0, 1, 2 ] > db.users.getIndexKeys(); # index情報を表示 [ { "_id" : 1 } ] > db.users.ensureIndex({"score":1}) # indexを作成 > db.users.getIndexKeys(); [ { "_id" : 1 }, { "score" : 1 } ] > db.users.dropIndex({"score":1}) # indexを削除 { "nIndexesWas" : 2, "ok" : 1 } > db.users.getIndexKeys(); [ { "_id" : 1 } ] > db.users.ensureIndex({"name":1},{"unique":true}) # nameについてuniqueのみ許可する > db.users.getIndexKeys(); [ { "_id" : 1 }, { "name" : 1 } ] > db.users.find().limit(1) { "_id" : ObjectId("53004852860d11e5c1173c83"), "name" : "user-0", "team" : 0, "score" : 28 } > db.users.insert({"name" : "user-0"}) # 存在する値を挿入するとエラーになる E11000 duplicate key error index: blog_app.users.$name_1 dup key: { : "user-0" } > db.users.remove({"name":{$regex:/user-[0-7]/i}}) # 正規表現を利用して削除 > db.users.find() { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 61 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "name" : "user-9", "team" : 0, "score" : 40 } > db.users.update({"name":"user-9"},{"score" : 100}) # scoreのみしか残らない > db.users.find() { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 61 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "score" : 100 } > db.users.update({"name":"user-8"},{$set:{"score" : 100}}) # 他のカラムも残す場合は、$setを利用する > db.users.find() { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 100 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "score" : 100 } > db.users.update({"name":"user-8"},{$inc:{"score" : -20}}) # scoreを20減らす > db.users.find() { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2, "score" : 80 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "score" : 100 } > db.users.update({"name":"user-8"},{$unset:{"score" : 1}}) # カラムを削除する > db.users.find() { "_id" : ObjectId("53004852860d11e5c1173c8b"), "name" : "user-8", "team" : 2 } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "score" : 100 } > db.users.update({"name":"user-8"},{$rename:{"team":"myteam"}}) # カラム名を変更する > db.users.find() { "_id" : ObjectId("53004852860d11e5c1173c8b"), "myteam" : 2, "name" : "user-8" } { "_id" : ObjectId("53004852860d11e5c1173c8c"), "score" : 100 } > exit bye root@akat:/home/akat# mkdir mongo root@akat:/home/akat# chown nobody:nogroup mongo/ root@akat:/home/akat# mongod --dbpath mongo --port 11111 # 11111portで起動
バックアップ、リストア
mongodumpについて記載
■メリット
・オンラインバックアップが可能
・データをバイナリ(BSON)形式でダンプするため、ファイルサイズを比較的小さく抑えられる
■デメリット
・データをバイナリ(BSON)形式でダンプするため、データの変換に時間がかかる
・インデックスはダンプされずにリストア時に再構築されるため、大きなインデックスがある場合にはリストアに時間がかかる
・小規模運用を前提に作成されている(データを一箇所に保存する、実行中はパフォーマンスに影響する)
root@akat:/home/akat# mongodump --db blog_app # jsonのバイナリを出力する、dumpというディレクトリが作成される connected to: 127.0.0.1 DATABASE: blog_app to dump/blog_app blog_app.system.indexes to dump/blog_app/system.indexes.bson 3 objects blog_app.entries to dump/blog_app/entries.bson 0 objects blog_app.users to dump/blog_app/users.bson 10 objects root@akat:/home/akat# mongo MongoDB shell version: 2.0.6 connecting to: test > show dbs admin (empty) blog_app 0.203125GB local (empty) test 0.203125GB > use blog_app # dbを削除する switched to db blog_app > db.dropDatabase() { "dropped" : "blog_app", "ok" : 1 } > show dbs admin (empty) local (empty) test 0.203125GB > exit bye root@akat:/home/akat# mongorestore # dumpというディレクトリの中を見て、リストアする connected to: 127.0.0.1 Sun Feb 16 22:21:18 dump/blog_app/entries.bson Sun Feb 16 22:21:18 going into namespace [blog_app.entries] Sun Feb 16 22:21:18 file dump/blog_app/entries.bson empty, skipping Sun Feb 16 22:21:18 dump/blog_app/users.bson Sun Feb 16 22:21:18 going into namespace [blog_app.users] 10 objects found Sun Feb 16 22:21:18 dump/blog_app/system.indexes.bson Sun Feb 16 22:21:18 going into namespace [blog_app.system.indexes] Sun Feb 16 22:21:18 { key: { _id: 1 }, ns: "blog_app.entries", name: "_id_" } Sun Feb 16 22:21:19 { key: { _id: 1 }, ns: "blog_app.users", name: "_id_" } Sun Feb 16 22:21:19 { key: { name: 1.0 }, unique: true, ns: "blog_app.users", name: "name_1" } 3 objects found root@akat:/home/akat# mongo MongoDB shell version: 2.0.6 connecting to: test > show dbs admin (empty) blog_app 0.203125GB local (empty) test 0.203125GB
参考
http://dotinstall.com/lessons/basic_mongodb