MongoDB

MongoDBを扱うために最低限知っておきたいこと


概要

以下観点でまとめたMongoDBの操作系簡易リファレンスです


  • とりあえずこれだけ知っていればMongoDBをデータストアとしたアプリ開発に入れる

  • 開発Teamメンバーに知っておいてほしいこと


前提


  • MongoDBがセットアップ済みであること

  • 参照、更新コマンド、クエリセレクタは最低限使えること


環境

使用環境
バージョン

CentOS
7.6

MongoDB server
4.0.5


状態確認


データベース一覧

> show dbs

admin 0.000GB
config 0.000GB
local 0.000GB


データベース切り替え(新規作成)

> use testdb

switched to db testdb


コレクション一覧

> show collections

company
department
user


初期化関連


コレクションtruncate

> db.user.remove({})


コレクション削除

> db.user.drop()


データベース削除

drop対象を指定した状態で実行

> use testdb

> db.dropDatabase()


設計・パフォーマンスチューニング


問い合わせプラン確認

> db.user.find({name:"koda"}).explain()


index確認

> db.user.getIndexes()


index作成(通常)

 value値 1:昇順、-1:降順

> db.user.createIndex({name: 1})


index作成(ユニーク)

> db.user.createIndex({name: 1}, {unique: true})


index作成(マルチフィールド)

> db.user.createIndex({name: 1, sex: 1})


ヘルプ・コマンド確認


ヘルプ

> help

db.help() help on db methods
db.mycoll.help() help on collection methods
sh.help() sharding helpers
(省略)


コマンド確認

 tab補完が使える


DBコマンド

> db.

db.adminCommand( db.fsyncLock( db.getWriteConcern( db.revokePrivilegesFromRole(
db.aggregate( db.fsyncUnlock( db.grantPrivilegesToRole( (省略)


コレクションコマンド

> db.user.

db.user.addIdIfNeeded( db.user.getCollection( db.user.mapReduce(
db.user.aggregate( db.user.getDB( db.user.propertyIsEnumerable
(省略)


コマンドライン実行


直接実行

$ echo $SHELL

/bin/bash

$ mongo --host localhost --quiet testdb --eval 'db.user.find()'
{ "_id" : ObjectId("5c7768915fd5d6ec50b38477"), "uid" : 1, "name" : "koda", "sex" : "男" }
{ "_id" : ObjectId("5c7768915fd5d6ec50b38478"), "uid" : 2, "name" : "mori", "sex" : "男" }
{ "_id" : ObjectId("5c7768915fd5d6ec50b38479"), "uid" : 3, "name" : "kubo", "sex" : "男" }


jsを実行


jsファイルを準備


find.js

var users = db.user.find();

users.forEach(function(user) {
if (user) {
print(user._id + '\t' + user.name + '\t' + user.sex);
}
});


実行

$ mongo --quiet testdb ./find.js

5c7768915fd5d6ec50b38477 koda 男
5c7768915fd5d6ec50b38478 mori 男
5c7768915fd5d6ec50b38479 kubo 男


バックアップ、レストア


ダンプ

$ mongodump --archive=/tmp/testdb.20190228.gz --gzip --db testdb


レストア

対象DBがない状態で実行

> show dbs

admin 0.000GB
config 0.000GB
local 0.000GB

$ mongorestore --gzip --archive=/tmp/testdb.20190228.gz --db testdb


エクスポート・インポート


エクスポート

$ mongoexport --db testdb --collection user --out /tmp/user.json


インポート

$ mongoimport --db testdb_new --collection user --file /tmp/user.json


シーケンス

オートインクリメント用の関数を作成しRDBのシーケンスのように利用する

> use testdb

countersコレクションを作成しておく

> db.counters.insert(

{
_id: "userid",
seq: 0
}
)

> db.counters.find()

{ "_id" : "userid", "seq" : 0 }

オートインクリメント関数を作成


  • 永続的に使える状態にするため、db.system.jsに登録しておく

  • Mongo shell上で定義した変数やfunctionはログオフで消えてしまうため


> db.system.js.save({_id:'my_seq', value:function (name) {
var ret = db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
});

確認のためにログオフ

> exit

bye

再接続

$ mongo

> use testdb

登録したスクリプトをロード

> db.loadServerScripts()

シーケンス取得

> my_seq('userid')

1
> my_seq('userid')
2
> my_seq('userid')
3

実際に使う場合はこんな感じ

> db.users.insert({_id: my_seq('userid'), name: "seq_test_user"} )

> db.users.find()
{ "_id" : 4, "name" : "seq_test_user" }


ユーザ認証

スーパーユーザを準備したうえでアプリ用ユーザを作成するイメージ


ユーザ管理者の登録


/etc/mongod.conf

#security:


> use admin

> db.createUser({

user:"admin",
pwd:"manager",
roles:[{ role:"userAdminAnyDatabase", db:"admin" }]
})


再起動

認証設定を有効にする


/etc/mongod.conf

security:

authorization: enabled

# systemctl restart mongod


アプリ用ユーザ登録

ユーザ管理者で再接続

$ mongo -u "admin" -p "manager" --authenticationDatabase="admin"

> use testdb

> db.createUser(

{
user: "airuser",
pwd:"airuser",
roles:[
{role:"readWrite", db:"testdb"}
]
}
)

cf. Built-In Roles


ロール変更

> use testdb

> db.updateUser(

"airuser",
{
roles:[
{role: "readWrite",db: "testdb"}
]
}
)


登録済みユーザ確認

> use admin

> db.system.users.find()


接続確認

アプリ用ユーザで接続

$ mongo --host localhost -u "airuser" -p "airuser" --authenticationDatabase="testdb"

許可DBだけ見える

> show dbs

testdb 0.000GB


おまけ


PHPでアクセス

ユーザ認証ありの状態で検証


ファイル準備


mongo.php

<?php

// DBへ接続
$mongo = new MongoClient("mongodb://localhost:27017/testdb",
array("username" => "airuser", "password" => "airuser"));
// データベースを指定
$db = $mongo->selectDB("testdb");
// コレクションを指定
$coll = $db->selectCollection("user");
// コレクションのドキュメントを取得
$docs = $coll->find(array('uid' => 1));
// 表示
foreach ($docs as $id => $obj) {
print_r($obj);
}
?>


実行

$ php mongo.php

Array
(
[_id] => MongoId Object
(
[$id] => 5c7787e73cf5a95585ea27f7
)

[uid] => 1
[name] => koda
[sex] => 男
)


フィールドを縦に展開

利用頻度が高いですよね

> db.user.find().pretty()

{
"_id" : ObjectId("5c7768915fd5d6ec50b38477"),
"uid" : 1,
"name" : "koda",
"sex" : "男"
}


  • cf.


    • MySQL: SQLの最後に \G

    • PostgreSQL: メタコマンド \x




参考