MongoDB

  • 投稿者:
  • 投稿カテゴリー:未分類

特徴

・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