ドキュメント指向のNoSQLとして人気があり、Web系のログ蓄積等で耳にするMongoDBを、こちらを参考に触ってみたのでまとめます。
MongoDBの主な特徴
- スキーマレス(データ構造の事前定義が不要)
- JOIN、トランザクションのサポートはない
- 水平分散による拡張性
MongDBのインストール
vi /etc/yum.repos.d/mongodb-org-4.0.repo
[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
yum install mongodb-org
systemctl start mongod
systemctl enable mongod
デフォルトは27017でListen
[root@localhost ~]# lsof -i :27017
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mongod 10642 mongod 10u IPv4 49590 0t0 TCP localhost:27017 (LISTEN)
firewall-cmd --add-port=27017/tcp --zone=public --permanent
firewall-cmd --reload
Mongoシェルの起動
コンソールでmongoと入力
[root@localhost ~]# mongo
MongoDB shell version v4.0.3
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("c94e5484-bc07-448d-a696-552294043074") }
MongoDB server version: 4.0.3
・・・・
test dbを作成(+接続も同時に実施される)
> use test
switched to db test
DBの状態を確認
> db.stats()
{
"db" : "test",
"collections" : 0,
"views" : 0,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 0,
"numExtents" : 0,
"indexes" : 0,
"indexSize" : 0,
"fileSize" : 0,
"fsUsedSize" : 0,
"fsTotalSize" : 0,
"ok" : 1
}
テストデータの挿入
db.user.insert({name:'mr.a', age:10, gender:'m', hobbies:['programming']});
db.user.insert({name:'mr.b', age:20, gender:'m', hobbies:['vi']});
db.user.insert({name:'ms.c', age:30, gender:'f', hobbies:['programming', 'vi']});
db.user.insert({name:'ms.d', age:40, gender:'f', hobbies:['cooking']});
データの確認: findがSQLのSELECT
> db.user.find()
{ "_id" : ObjectId("5bd6be298d280c3a544ebce6"), "name" : "mr.a", "age" : 10, "gender" : "m", "hobbies" : [ "programming" ] }
{ "_id" : ObjectId("5bd6be298d280c3a544ebce7"), "name" : "mr.b", "age" : 20, "gender" : "m", "hobbies" : [ "vi" ] }
{ "_id" : ObjectId("5bd6be298d280c3a544ebce8"), "name" : "ms.c", "age" : 30, "gender" : "f", "hobbies" : [ "programming", "vi" ] }
{ "_id" : ObjectId("5bd6be2b8d280c3a544ebce9"), "name" : "ms.d", "age" : 40, "gender" : "f", "hobbies" : [ "cooking" ] }
>
RDBとMongoDBの用語比較
RDB | MongoDB |
---|---|
データベース | データベース |
表 | コレクション |
行(レコード) | ドキュメント |
列 | フィールド |
条件演算
クエリセレクタ:{フィールド名:値}で条件を渡す
年齢が20歳以上の男性を抽出 比較演算子
> db.user.find({age:{$gte:20}, gender:'m'})
{ "_id" : ObjectId("5bd6be298d280c3a544ebce7"), "name" : "mr.b", "age" : 20, "gender" : "m", "hobbies" : [ "vi" ] }
配列
配列もその他のフィールド(列)と同様に検索可能
> db.user.find({hobbies:'cooking'})
{ "_id" : ObjectId("5bd6be2b8d280c3a544ebce9"), "name" : "ms.d", "age" : 40, "gender" : "f", "hobbies" : [ "cooking" ] }
取得フィールド(列)の指定
SELECT 列名相当は、findの第2引数に取得するフィールド名を指定
{フィールド名:0}以外の数字で表示、{フィールド名:0}で非表示
> db.user.find({}, {age:0})
{ "_id" : ObjectId("5bd6be298d280c3a544ebce6"), "name" : "mr.a", "gender" : "m", "hobbies" : [ "programming" ] }
{ "_id" : ObjectId("5bd6be298d280c3a544ebce7"), "name" : "mr.b", "gender" : "m", "hobbies" : [ "vi" ] }
{ "_id" : ObjectId("5bd6be298d280c3a544ebce8"), "name" : "ms.c", "gender" : "f", "hobbies" : [ "programming", "vi" ] }
{ "_id" : ObjectId("5bd6be2b8d280c3a544ebce9"), "name" : "ms.d", "gender" : "f", "hobbies" : [ "cooking" ] }
> db.user.find({}, {age:1})
{ "_id" : ObjectId("5bd6be298d280c3a544ebce6"), "age" : 10 }
{ "_id" : ObjectId("5bd6be298d280c3a544ebce7"), "age" : 20 }
{ "_id" : ObjectId("5bd6be298d280c3a544ebce8"), "age" : 30 }
{ "_id" : ObjectId("5bd6be2b8d280c3a544ebce9"), "age" : 40 }
Update
下記で更新可能
db.コレクション名.update({検索条件}, {$set:{更新内容}})
※$setがないと、検索条件列が更新内容の値でUpdateされるので注意
> db.user.find({name:"mr.a"})
{ "_id" : ObjectId("5bd6be298d280c3a544ebce6"), "name" : "mr.a", "age" : 10, "gender" : "m", "hobbies" : [ "programming" ] }
> db.user.update({name:'mr.a'}, {$set:{gender:'X'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find({name:"mr.a"})
{ "_id" : ObjectId("5bd6be298d280c3a544ebce6"), "name" : "mr.a", "age" : 10, "gender" : "X", "hobbies" : [ "programming" ] }
特定ドキュメント(行)にフィールド(列)追加も可能
存在しないフィールドを更新し、名前がmr.bの人のレコードに、hoge:111という新しいフィールドを追加
> db.user.update({name:'mr.b'}, {$set:{hoge:111}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5bd6be298d280c3a544ebce6"), "name" : "mr.a", "age" : 10, "gender" : "X", "hobbies" : [ "programming" ] }
{ "_id" : ObjectId("5bd6be298d280c3a544ebce7"), "name" : "mr.b", "age" : 20, "gender" : "m", "hobbies" : [ "vi" ], "hoge" : 111 }
Upsert
データが存在しなければINSERT、存在すればUPDATE
存在しない=コレクション(表)が無い場合と、該当ドキュメント(行)が無い場合
共になければ自動的に作成、あればUPDATEされる
例)db.counter.update( {type:'success'} ,{$inc:{count:1}}, true)
$incは、対象の値を増分
> db.counter.update( {type:'error'} ,{$inc:{count:1}}, true)
> db.counter.update( {type:'error'} ,{$inc:{count:1}}, true)
> db.counter.update( {type:'error'} ,{$inc:{count:1}}, true)
> db.counter.update( {type:'success'} ,{$inc:{count:1}}, true)
> db.counter.find()
{ "_id" : ObjectId("5bd7b8b5d6949f96aeb75451"), "type" : "error", "count" : 3 }
{ "_id" : ObjectId("5bd7b8fcd6949f96aeb7545a"), "type" : "success", "count" : 1 }
複数件同時更新
db.user.update({}, {$set:{gender:'X'}},false,true)
※第三引数:upsert (false:存在しないレコードは更新しない)
第四引数:trueにして、複数件を更新
> db.user.find({},{_id:0})
{ "name" : "mr.a", "age" : 10, "gender" : "X", "hobbies" : [ "programming" ] }
{ "name" : "mr.b", "age" : 20, "gender" : "m", "hobbies" : [ "vi" ], "hoge" : 111 }
{ "name" : "ms.c", "age" : 30, "gender" : "f", "hobbies" : [ "programming", "vi" ] }
{ "name" : "ms.d", "age" : 40, "gender" : "f", "hobbies" : [ "cooking" ] }
> db.user.update({}, {$set:{gender:'X'}}, false, true)
WriteResult({ "nMatched" : 4, "nUpserted" : 0, "nModified" : 3 })
> db.user.find({},{_id:0})
{ "name" : "mr.a", "age" : 10, "gender" : "X", "hobbies" : [ "programming" ] }
{ "name" : "mr.b", "age" : 20, "gender" : "X", "hobbies" : [ "vi" ], "hoge" : 111 }
{ "name" : "ms.c", "age" : 30, "gender" : "X", "hobbies" : [ "programming", "vi" ] }
{ "name" : "ms.d", "age" : 40, "gender" : "X", "hobbies" : [ "cooking" ] }
Remove
ドキュメント(行)削除
db.user.remove()
> db.user.remove({age:{$gte:30}})
WriteResult({ "nRemoved" : 2 })
> db.user.find({},{_id:0})
{ "name" : "mr.a", "age" : 10, "gender" : "X", "hobbies" : [ "programming" ] }
{ "name" : "mr.b", "age" : 20, "gender" : "X", "hobbies" : [ "vi" ], "hoge" : 111 }
Sort,Count
sort: {フィールド:1(昇順)}、{フィールド:ー1(降順)}
count: count()
> db.user.find({},{_id:0}).sort({age:1})
{ "name" : "mr.a", "age" : 10, "gender" : "X", "hobbies" : [ "programming" ] }
{ "name" : "mr.b", "age" : 20, "gender" : "X", "hobbies" : [ "vi" ], "hoge" : 111 }
> db.user.find({},{_id:0}).sort({age:-1})
{ "name" : "mr.b", "age" : 20, "gender" : "X", "hobbies" : [ "vi" ], "hoge" : 111 }
{ "name" : "mr.a", "age" : 10, "gender" : "X", "hobbies" : [ "programming" ] }
> db.user.find({}).count()
2