概要
-
MongoDB = ドキュメント指向のDB
- ドキュメント = 構造化されたデータのこと
- RDBのレコードに相当する
- これを単位としてデータを扱う
- ドキュメントは、主キーとして
_id
を必ず持つ - ドキュメントはJSONのように扱える(内部的にはBSON)
- データは型付けされる(BSON互換)
- コレクション = データの集まり
- RDBのテーブルに相当する(ただしスキーマは存在しない)
- SQLのような複雑なデータ操作はできない
- 検索機能としては柔軟に対応できる
- ドキュメント = 構造化されたデータのこと
-
企業(MongoDB Inc.)が開発し、オープンソースで公開されている
- 有料版が存在し、セキュリティ強化などの追加機能とサポートが受けられる
- その他、コンサルや教育も受け付けているとのこと
-
GNU APGLライセンス
-
クロスプラットフォーム
-
C++実装
-
スケーリング/クラスタリングに対応している
-
スクリプト言語としてJavaScriptを採用している
-
復数の言語のドライバ(バインディング)を提供
導入
導入方法は公式にプラットフォーム別の詳細な説明があるので参照のこと。
インストール
OSXの場合はbrewでインストールできる。
$ brew update
$ brew install mongodb --with-openssl
Linuxの場合も同様にパッケージマネージャを使うか、.rpmなどからインストール可能。
CentOS6.xの場合はリポジトリを登録し、
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
その後yumで通る。
$ sudo yum install mongodb-org
起動
mongod
でサーバを起動する。
$ mongod
$ service mongod start
OSXの場合はデフォルトで/data/db/
にデータが置かれるので、このディレクトリを作って権限設定しないと失敗する。
インストール後の起動方法についても公式の説明があるので参照のこと。
Mongo Shell
Mongo Shell = mongo
コマンドで起動する対話型のコンソールのこと。
JavaScript(風のスクリプト)を使う。
# mongodに接続
$ mongo
help
でヘルプ表示、Tabで補完ができる。
公式のSQLとMongoの対応表がわかりやすかった。
状態を表示する(show)
show <表示内容>
でDBの状態を表示できる。
show dbs // DBの一覧
show collections // 使用中のDB中のコレクション一覧
show users // ユーザの一覧
show roles // ロールの一覧
DBを選択する/作成する(use)
use
により、DBを切り替えて利用できる。
また存在しないDBを指定した場合、そのDBが新たに作成される。
// DB(somedb)を選択
use somedb
コレクションを追加/削除する(createCollection/drop)
createCollection()
により、コレクションを新規に作成できる。
また後述するinsert
によって存在しないDBにドキュメントを挿入した場合も、自動的にそのコレクションが作成される。
// 利用中のDBにコレクションfooを追加
db.createCollection('foo')
コレクションを削除する場合はdrop()
を使う。
// コレクションfooを削除
db.foo.drop()
代入する
シェル内ではjsと同様に、変数に任意のオブジェクトを代入できる。
// insertの結果をresultに代入
result = db.foo.insert({...})
挿入する(insert)
insert()
を使う。
またショートハンドとしてinsertOne()
, insertMany()
も存在する。
挿入時に、そのドキュメントの直下に自動的に _id
が含まれる。
// abcコレクションにドキュメントを挿入
db.abc.insert({
'name' : 'Alpha',
'file' : {
'name' : 'test file',
'text' : '...',
}
)
検索する(find)
find()
を使う。
またショートハンドとしてfindOne()
なども存在する。
全件検索する
全件検索する場合は単にfind()
を呼ぶ。
// 単にfindすると全件を取得する
db.abc.find()
条件指定する
条件を指定する場合はfind()
の引数として渡す。
// トップレベルの項目nameを検索する
db.abc.find({
'name' : 'Alpha'
})
階層を指定する場合は、条件のキーをドット区切りで表記する。
// file.nameを検索する
db.abc.find({
'file.name' : 'test file',
})
配列内の要素を検索する場合は、
'<配列自身のキー>.<配列の要素の任意のキー>' : '<配列の要素の値>'
// 各ドキュメントがこんな構造だったとして:
// {
// 'list' : [
// {'name' : 'item1', ...}
// {'name' : 'item2', ...}
// {'name' : 'item3', ...}
// ]
// }
// listの中にある、名前がAlphaの要素を検索する場合は:
db.abc.find({
'list.name' : 'item1'
})
比較する
検索条件に演算子を用いる場合は、
<キー>: { <演算子> : '<比較値>' }
// file.sizebytes > 1024
db.abc.find({
'file.sizebytes' : { $gt: 1024 }
})
演算子は$gt
のように定数によって指定できる。(一覧)
演算子 | 意味 |
---|---|
$eq | == |
$ne | != |
$lt | < |
$lte | <= |
$gt | > |
$gte | >= |
$in | 配列に含まれる |
$nin | 配列に含まれない |
複合条件で検索する
ANDの場合は単に条件を列挙すればいい。
db.abc.find({
'name' : 'alpha',
'file.name' : 'test file',
})
ORの場合は、定数$or
を指定する。
db.abc.find({
$or : [
{ 'name' : 'alpha' },
{ 'file.name' : 'test file' }
],
})
条件指定する(count)
件数のみを取得したい場合はcount()
を使う。
// nameがalphaのドキュメントの件数を返す
db.abc.count({
'name' : 'alpha',
})
ソートする(sort)
find()
による検索結果に対してsort()
を実行する。
ソート条件は1 = ASC, -1 = DESC
// serialの降順でソートする
db.abc.find().sort({
'serial' : -1
})
正規表現を使う
検索条件には正規表現を使うことができる。
jsと同じリテラルを使って書ける。
// nameがa/Aからはじまるドキュメントを検索
db.abc.find({
'name' : /^a.*/i
})
更新する(update)
update()
を使う。
またショートハンドとしてupdateOne()
, updateMany()
も存在する。
なお_id
は更新できない。
またMongoにおける書き込み操作は__ドキュメント単位でのアトミック__が保証される。
ドキュメントを部分的に更新する
update(
<検索条件>,
{
$set : <更新内容>,
$currentData : <現在時刻を更新する項目>,
},
{
multi: <復数更新の有無>,
}
)
// nameがalphaのドキュメントを探し、特定の値を更新する
// 更新の際にupdated_atを現在時刻に更新する
db.abc.update({
{
'name' : 'alpha',
},
{
$set : {
// find()と同様にドット区切りで指定できる
'file.name' : 'some filename updated',
},
$currentDate : {
'updated_at' : true,
},
},
})
ドキュメント全体を更新する
update(
<検索条件>,
<置換えるドキュメント>,
)
// nameがalphaのドキュメントを探し、まるごと置換える
db.abc.update({
{
'name' : 'alpha',
},
{
'name' : 'alpha updated',
// ...
},
})
削除する(remove)
remove(
<検索条件>,
{
justOne : <削除対象を1件に限定する場合はtrue>,
},
)
全件削除する
空のオブジェクトを渡してremove()
すると全件削除される。
なお引数なしの状態で呼ぶとエラーとなり、削除されない。
// 全件削除する
db.abc.remove({})
条件を指定して削除する
// nameがalphaのドキュメントを削除する
db.abc.remove({
'name' : 'alpha',
})
WriteResult()について
Mongoは書き込みを伴う処理の戻り値として、WriteResult()
を返す。
以下のようなプロパティを持っていて、結果を識別できる。
プロパティ | 内容 |
---|---|
nInserted | 挿入された件数 |
nMatched | 更新対象となった件数 |
nModified | 更新された件数 |
nRemoved | 削除された件数 |
特殊なデータの扱いについての特記事項
日付
日付の扱い方は2つある。
- 文字列で保持する方法:
Date()
を使う - Unixエポックミリ秒で保持する方法:
ISODate()
を使う
比較/計算は後者のほうが簡単にできそうだが標準時刻になってしまうのが難点。
ベストプラクティスは未調査。
バイナリ
サイズの上限については公式に環境別のData Sizeの上限があるが、見る限りTB単位の数なので通常利用するぶんには問題なさそう。
設定
DBやコレクションに個別の設定は、旧来のRDBと同様にMongo Shellを使って設定していく。
全体的な設定は設定ファイル(mongod.conf
など)として記述し、サーバの起動時に読み込む。
コマンドで直接起動する場合は--config
オプションを使って設定を指定する。
$ mongod --config /path/to/mongod.conf
設定ファイルはYAML形式で記述する。
インデックス
インデックスの概念については他のDBと同じ。
検索速度の向上や、ユニーク制約のために設定する。
Mongoはドキュメントに自動的に_id
を設定するが、この_id
に対してはインデックスも自動的に割当たる。
このインデックスはユニーク制約を持つため、_idを重複して挿入することができないようになっている。
インデックスの作成/確認/削除はコマンドで行う。
// abcコレクションのfile.nameに対して、昇順かつユニークのインデックスを作成
db.abc.createIndex({
{ 'file.name' : 1 },
{ 'unique' : true },
})
// 設定済のインデックスを確認
db.some.getIndexes()
// インデックスを削除
db.some.dropIndex(
{ 'file.name' : 1 }
)
ユーザ/ロール/認証
Mongoではユーザとロールの単位で権限を管理する。
管理ユーザの作成
まずは認証を特に指定しない状態でMongoを起動し、管理用のDBと、その管理者を設定する。
use admin
db.createUser({
user: "userAdmin",
pwd: "some_password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
サーバ側(mongod)を終了し、認証を有効にした状態で再起動する。
認証機能は、コマンドの--auth
オプションか設定ファイルによって指定可能。
$ mongod --auth
これ以降、ユーザの作成・管理にはこの管理者ユーザの認証が必要となる。
また管理者ユーザによって権限を与えられたユーザで認証しない限り、DBへのアクセスができなくなる。
認証するためにはクライアント側の接続時に指定するか、auth()
を使う。
// 接続時に認証する
$ mongo -u 'userAdmin' -p 'some_password' --authenticationDatabase 'admin'
// 接続後に認証する
db.auth('userAdmin', 'some_password')
一般ユーザの作成
管理ユーザと同様に、createUser()
によってユーザを作成できる。
対象のロールおよびDBは復数指定することができる。
db.createUser(
{
user: "alpha",
pwd: "some_password",
roles: [ { role: "readWrite", db: "alpha" },
{ role: "read", db: "bravo" } ]
}
)
ロールの種類について
ロールはMongo標準のビルトインロールの中から選んで指定できる。
またロールを自分で作成することもできる。
TODO
- コマンドの詳細
- 設定項目の詳細
- 暗号化
- 通信の暗号化(TLS/SSL)
- ストレージの暗号化
- レプリケーション
- シャーディング(クラスタリング)
- API/ドライバ