MongoDB

概要

MongoDBはRDBMSではなく、いわゆるNoSQLと呼ばれるデータベースに分類されるものである。RDBMSのようにレコードをテーブルに格納するのではなく、「ドキュメント」と呼ばれる構造的データをJSONライクな形式で表現し、そのドキュメントの集合を「コレクション」として管理する（このデータの物理的な格納はBSONと呼ばれるJSONのバイナリ版といえる形式で行われる）。コレクションはRDBMSのような固定的なスキーマを持たない。ドキュメントには複雑な階層構造を持たせることもでき、それらの構造に含まれるフィールドを指定したクエリやインデクス生成も簡単な指定によって行える。RDBMSのように高度な結合操作を効率的に行うことはできないが、データの追加・更新・削除・クエリは高速に行うことができる。また、アプリケーションは自身の構造やデータ型に合った自然な形でデータを格納することができるため、扱うデータの特性によっては、RDBMSよりも容易かつ迅速に開発を行える可能性がある。
Mongoという名前は、英語で「ばかでかい」を意味する "humongous" に由来する。
MongoDBの開発は10gen（現MongoDB Inc.）によって2007年10月から開始され、最初の公開リリースは2009年2月に行われた。
2014年12月にデータベースストレージエンジンのWiredTigerを買収し、2015年のメジャーアップデートリリースのバージョン3.0より内部に組み込まれた。ドキュメント単位でのロックが可能になったことで特にデータ書き込み時においてのパフォーマンスが改善している。
人気のあるデータベースをランキング形式で公表しているDB-Enginesによると2018年2月の時点でOracle Database、MySQL、Microsoft SQL Server、PostgreSQL等の歴史あるRDBMSプロダクトに続き5位となっており、2000年代後半より多数作られたNoSQLデータベースの中で頭一つ抜けたシェアを占めている。
2019年1月にAWSによってMongoDB互換のAmazon DocumentDBがリリースされた。

アドホックなクエリ

MongoDBでは、任意のフィールドを好きな時にクエリできる。フィールドの完全一致に加えて、範囲をもつクエリ、正規表現検索など様々な種類のクエリが使える。ユーザ定義のJavaScript関数を述語として使うこともできる（関数がtrueを返したときにドキュメントがマッチする）。
クエリでは、（全フィールドをとりだす代わりに）指定したフィールドだけを取り出せる。また、ソートを行ったり、結果の数を制限したり、一部をスキップすることもできる。

ネストされたフィールドのクエリ

埋め込みオブジェクトおよび配列にも「たどりつく」ことができる。以下のオブジェクトが users コレクションに挿入されているとする：
{
    "username" : "bob",
    "address" : {
        "street" : "123 Main Street",
        "city" : "Springfield",
        "state" : "NY"
    }}
このドキュメント（およびNYの住所をもつすべてのドキュメント）は、以下のクエリで取得できる:
> db.users.find({"address.state" : "NY"})
配列の要素を指定することもできる：
> db.food.insert({"fruit" : ["peach", "plum", "pear"]})> db.food.find({"fruit" : "pear"})

インデックス

MongoDBは、追加のインデックスをサポートする。インデックスは、単一キー、複合キー、ユニーク/非ユニーク、地理空間インデクスをサポートする。ネストされたフィールドもインデックスできるし、配列型をインデックスすると配列内の各要素がインデックスされる。
MongoDBのクエリオプティマイザはクエリの実行時にいくつかのクエリ計画を試し、最速のものを選択する。定期的に再サンプリングを行う。開発者は使用されるインデックスを explain 関数で見ることができ、 hint 関数で異なるインデックスを参照できる。
インデックスはいつでも作成・削除できる。

集約

アドホックなクエリに加えて、MongoDBは集約のためのいくつかのツールをサポートしている。これには、SQLのGROUP BYに似たgroup関数や、MapReduceなどがある。

ファイルストレージ

MongoDBは、GridFSと呼ばれるプロトコルを実装しており、これを使うことで大きなファイルをデータベースに格納・取得することができる。このファイルストレージ機構はnginxやlighttpd のプラグインからも使用できる。

サーバサイドJavaScript実行

JavaScriptはMongoDBにおけるLingua franca（共通語）であり、クエリや集約関数（MapReduce等）で使用したり、データベースに直接送信して実行できる。
クエリでのJavaScriptの例:
> db.foo.find({$where : function() { return this.x == this.y; }})
データベースに送信して実行させるコードの例:
> db.eval(function(name) { return "Hello, "+name; }, ["Joe"])
これは "Hello, Joe" を返す。
JavaScriptの変数はデータベースに格納でき、他のJavaScriptからグローバル変数として利用できる。関数を含むすべての正当なJavaScript型を格納できるため、JavaScriptを「ストアドプロシージャ」として利用できる。

Cappedコレクション

MongoDBは、Cappedコレクションと呼ばれる固定サイズのコレクションもサポートしている。Cappedコレクションはサイズ（オプションで要素数も使える）を指定して作成される。capped collectionsは、挿入した順にコレクションを管理する: 指定したサイズに到達したら、古いものから順に削除される。
Cappedコレクションでは、tailable cursorと呼ばれる特殊なカーソルを利用できる。このカーソルの名前は tail -f に由来し、結果を返し終えてもクローズせずに待機し続けて、それ以降に追加されたドキュメントを返却しつづける。

デプロイ

MongoDBはソースファイルからビルドすることもできるが、より一般的にはバイナリパッケージからインストールされる。多くのLinuxパッケージ管理システムはMongoDBのパッケージを含んでいる: CentOSとFedora, DebianとUbuntu, Gentoo, Arch Linux。  公式Webサイトから入手することもできる。
MongoDBはメモリマップトファイルを用いるため、32-bitシステムではサイズが2GBに制限される。 MongoDBのサーバはリトルエンディアンのシステムのみで動作する。ただし、ほとんどのドライバはビッグエンディアンのシステムでも動作する。

レプリケーション

MongoDBは、レプリカセット (Replica Sets) と呼ぶ仕組みによって高い可用性を提供する。1つのレプリカセットはデータの2つ以上のコピーからなる。レプリカセットの各メンバーは、常時、プライマリレプリカもしくはセカンダリレプリカとしての役割を果す。プライマリレプリカはすべての書き込みおよび読み込みを実行する。セカンダリレプリカは、組み込みのレプリケーションを用いて、プライマリにあるデータのコピーを保持する。プライマリレプリカが機能しなくなった時は、レプリカセットが自動的に投票プロセスを開始して、どのセカンダリがプライマリになるべきかを決定する。

シャーディング（Sharding）

MongoDBは、シャーディング（Sharding）というシステムによって水平スケーリングが可能である。これはBigTableやPNUTSのスケーリングモデルに非常に良く似ている。開発者はshardキーを選択し、このキーがデータをどのように分散させるかを決める。データ中のキーを元にデータを分散させるshardが決められる。（一つのshardは1つ以上のスレーブを持つマスタである）
アプリケーションはいくつかの操作を行う際に、shardingされたクラスタと対話していることを認識している必要がある。例えば "findAndModify" クエリは、shardされたコレクションからクエリをするときにshardキーを含む必要がある。 アプリケーションは、mongosと呼ばれる特別なルーティングプロセスと対話する。このプロセスは、shardクラスタを単一のMongoDBサーバに見えるようにする。mongosプロセスはどのデータがどのshardにあるかを知っており、クライアントのリクエストを適切にルーティングする。すべてのリクエストはこのプロセスを通して流れる: リクエストやレスポンスを転送するだけでなく、必要に応じてマージやソートも行う。 mongosプロセスはいくつでも実行できるが、通常は1つのアプリケーションに対して1つが推奨される。

公式ツール

最もパワフルで便利な管理ツールはデータベースシェルの mongo である。このシェルは、データベースの内容を閲覧・挿入・削除・更新する機能を提供すると同時に、レプリケーション情報を取得したり、shadingを設定したり、サーバを停止したり、JavaScriptを実行したりすることができる。mongoは、SpiderMonkeyの上に構築されているため、MondoDBサーバに接続できると同時に、完全なJavaScriptシェルでもある。
管理情報にはWebベースのadminインタフェースを通してもアクセスできる。これは、現在のサーバ情報を送信するシンプルなHTMLのWebページである。デフォルトでは、このインタフェースにはデータベースのポートの1000番上のポート (http://localhost:28017) からアクセスできる。--norestオプションによってこの機能を無効化できる。
mongostat は、直近の統計情報のシンプルな一覧を表示するコマンドラインツールである。挿入された数、更新された数, 削除された数, クエリの数, 実行されたコマンドの数, データベースがロックされた時間のパーセンテージ、メモリの使用状況などを表示する。
mongosniff は、MongoDBのネットワークトラフィックを覗くツールである。

ライセンスとサポート

MongoDB Community Serverは、Server Side Public License (SSPL) の下で利用できる。 元々はGNU Affero General Public License (AGPL) が適用されていたが、クラウド事業者がMongoDBをSaaSとして提供しながらコミュニティに還元しないことが問題となり、2018年10月16日をもってより厳しいSSPLへと移行した。言語ドライバはApache Licenseライセンスの下で利用できる。