特徴
・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