52
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

##概要

以下観点でまとめた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

##参考

52
53
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?