NoSQLのデータベースMongoDBを触ってみよう「IT」

ドキュメント指向データベースMongoDB入門

株式会社エルデ 土屋勝

 現在のWebアプリケーションはMySQLやPostgreSQL、Microsoft SQL Server、Oralce Databaseなどのデータベースで情報を管理し、PHPやJava、JavaScriptなどでページを作成する動的ページが主流となっています。これらのデータベースはいずれもSQL文で操作できる、リレーショナルデータベース管理システム(RDBMS)です。

 RDBMSは小規模システムから企業の基幹系まで広く使われていますが、限界も指摘されています。その一つとしてWebシステムが大規模化し、大量のデータを扱う必要になった時にスケーラビリティに対応しにくいということが挙げられます。フロントエンドであるWebサーバーは分散処理で大量アクセスに対処できますが、RDBMSは簡単に分散処理ができないため、そこがボトルネックになってしまうのです。

 そこで提唱されたのが、RDBMSとは異なるデータ管理方法を採用し、SQLに頼らない「NoSQL系データベース」です。NoSQLにもさまざまな種類、考え方があります。今回はRDBMSとの親和性が高く、SQLに慣れ親しんでいるエンジニアにも取っつきやすい製品としてMongoDBを紹介します。

MongoDBはテーブル定義を持たない

 MongoDBはNoSQLの1分野である、ドキュメント指向データベースの代表的な製品で、GNU Affero General Public License(GNU AGPL)ライセンスで公開されています。データはJSON形式で保存され、テーブル定義(スキーマ)が必要ありません。同じコレクションにあるドキュメントの構造が異なっていても問題無く、更新ごとにドキュメントの構造を変更できます。テーブルのスキーマが変更されてもアプリケーション側だけ修正すればよく、DB側の修正は不要です。

 スキーマが無いこと、JOINが無いことを除けばRDBMSと同じようなことが可能です。SQLで言えば「where」や「like」を使った複雑な検索を行うことができ、SUM、AVGなど集計機能も持っています。

 MongoDBが得意とするケースとしては、Webサイトのコンテンツ管理、コメントの管理、投票、ユーザー登録、大量データ処理、統計、解析、イベントログの取得といったものが挙げられます。実際にMTV Networks、foursquare、The New York Times、Ameba Pico(アメーバピグの海外向けサービス)などでMongoDBが使われています。

 また、多くの言語に対し公式・非公式ドライバが用意されています。現在、C、C++、C#、Java、JavaScript、Perl、PHP、Python、Ruby、.NETなどがサポートされています。

MongoDBをインストールする

 MongoDBの公式サイトにアクセスし、必要なインストールパッケージをダウンロードします。

http://www.mongodb.org/

 原稿執筆時点で最新版は開発バージョンが2.7.2、安定バージョンが2.6.3となっています。ここではWindows 64bit用安定バージョンのmongodb-win32-x86_64-2008plus-2.6.3.zipを選びました。

mongo01

MongoDBの公式サイトからインストールパッケージをダウンロードする

 zipファイルを展開します。できあがったmongodb-win32-x86_64-2008plus-2.6.3フォルダをmongodbとリネームし、適当な場所に置きます。自分はC:ドライブ直下c:\mongodbとしました。

 次にデータベースを保管する場所を決め、フォルダを作ります。

D:\home\mongo\data

 としました。

 このデータベース保管場所を指定するmogodb.configファイルを作ります。中身は

dbpath=d:\home\mongo\data

 と記述します。

 このファイルはどこに置いてもいいのですが、mongodb\binとしました。スタートメニューから[コントロールパネル][システムとセキュリティ][システム][システムの詳細設定]と開き、[環境変数]をクリックしてユーザー環境変数、あるいはシステム環境変数の「path」にc:\mongodb\binを追加しておきましょう。

MongoDBを動かす

 MongoDBサーバーを起動します。コマンドプロンプトを開き、以下のように入力します。

mongod –config c:\mongodb\bin\mongodb.config

 MongoDBサーバーが起動します。このコマンドプロンプトはMongoDBを使っている間はずっと開いたままにしておきます。

mongo02

MongoDBサーバーを起動したところ

 MongoDBの操作はmongdシェルを通じて行います。別のコマンドプロンプトを開き、

mongo

 と入力します。この画面がmongoシェルで、mongoと対話的に操作を行うことができます。たとえば

db.version()

db.stats()

 と入力してみましょう。MongoDBのバージョンと状態が表示されます。

mongo03

mongdシェルではMongoDBと対話的操作を行うことができる

データを登録し、検索を行う

 サンプルデータを登録してみましょう。ザ・ビートルズの6人に登場してもらいました。「あれ、ザ・ビートルズは4人組じゃなかったか」と思われるかもしれませんが、ピート・ベストとスチュワート・サトクリフはメジャーデビュー以前のメンバーです。MongoDBのデータ登録は「db.オブジェクト名.insert」です。オブジェクトが存在しなければ自動的に生成されます。

> db.beatles.insert({name:'Jhon Lennon',year_of_birth:1940,month_of_birth:10,date_of_birth:9, year_of_death:1980,month_of_death:12,date_of_death:8,part:
'Guiter,Keyboard,Base,Harmonica'})
db.beatles.insert({name:'George Harrison',year_of_birth:1943,month_of_birth:2,date_of_birth:25, year_of_death:2001,month_of_death:11,date_of_death:29,part:
'Guiter,Sitar,Keyboard'})
db.beatles.insert({name:'Paul McCartney',year_of_birth:1942,month_of_birth:6,date_of_birth:18,
part:'Base,Guiter,Keyboard,Drums'})
db.beatles.insert({name:'Ringo Starr',year_of_birth:1940,month_of_birth:7,date_of_birth:7,
part:'Drums'})
db.beatles.insert({name:'Pete Best',year_of_birth:1941,month_of_birth:11,date_of_birth:24,
part:'Drums'})
db.beatles.insert({name:'Stuart Sutcliffe',year_of_birth:1940,
month_of_birth:6,date_of_birth:23,year_of_death:1962,
month_of_death:4,date_of_death:10,part:'Base'})
>

 故人であるジョン、ジョージ、スチュは死亡年月日がありますが、存命であるポール、リンゴ、ピートにはこの項目がありません。このようにMongoDBはレコードごとにスキーマが異なっていても問題ありません。

 すべてのデータを表示するコマンドはdb.オブジェクト名.find()です。

> db.beatles.find()
{ "_id" : ObjectId("52a7fab21655f99e859ee3d5"), "name" : "Jhon Lennon", "year_o
f_birth" : 1940, "month_of_birth" : 10, "date_of_birth" : 9, "year_of_death" : 1
980, "month_of_death" : 12, "date_of_death" : 8, "part" : "Guiter,Keyboard,Base,
Harmonica" }
{ "_id" : ObjectId("52a7fab21655f99e859ee3d6"), "name" : "George Harrison", "yea
r_of_birth" : 1943, "month_of_birth" : 2, "date_of_birth" : 25, "year_of_death"
: 2001, "month_of_death" : 11, "date_of_death" : 29, "part" : "Guiter,Sitar,Keyb
oard" }
{ "_id" : ObjectId("52a7fab21655f99e859ee3d7"), "name" : "Paul McCartney", "year
_of_birth" : 1942, "month_of_birth" : 6, "date_of_birth" : 18, "part" : "Base,Gu
iter,Keyboard,Drums" }
{ "_id" : ObjectId("52a7fab21655f99e859ee3d8"), "name" : "Ringo Starr", "year_of
_birth" : 1940, "month_of_birth" : 7, "date_of_birth" : 7, "part" : "Drums" }
{ "_id" : ObjectId("52a7fab21655f99e859ee3d9"), "name" : "Pete Best", "year_of_b
irth" : 1941, "month_of_birth" : 11, "date_of_birth" : 24, "part" : "Drums" }
{ "_id" : ObjectId("52a7fab21655f99e859ee3da"), "name" : "Stuart Sutcliffe", "ye
ar_of_birth" : 1940, "month_of_birth" : 6, "date_of_birth" : 23, "year_of_death"
 : 1962, "month_of_death" : 4, "date_of_death" : 10, "part" : "Base" }
>

「_id」はRDBMSでは「primary key」に相当し、「ObjectId」はMongoDBが自動的に割り振った一意な文字列です。

 条件検索を行うには、括弧の中にキーワードを記述します。たとえばドラムを担当していたメンバーを抽出するにはdb.beatler.find({part:’Drums’})と入力します。また、_idは隠してしまいましょう。

> db.beatles.find({part:'Drums'},{"_id":0})
{ "name" : "Ringo Starr", "year_of_birth" : 1940, "month_of_birth" : 7, "date_of_birth" : 7, "part" : "Drums" }
{ "name" : "Pete Best", "year_of_birth" : 1941, "month_of_birth" : 11, "date_of_birth" : 24, "part" : "Drums" }
>

 リンゴ・スターとピート・ベストの2人が表示されました。ポール・マッカートニーもドラムを担当しているのに表示されません。これはポール・マッカートニーがドラムだけではなく、ベースやキーボードも担当しているからです。この場合は「$OR」と正規表現を使います。

> db.beatles.find({part:'Drums'},{"_id":0})
{ "name" : "Ringo Starr", "year_of_birth" : 1940, "month_of_birth" : 7, "date_of_birth" : 7, "part" : "Drums" }
{ "name" : "Pete Best", "year_of_birth" : 1941, "month_of_birth" : 11, "date_of_birth" : 24, "part" : "Drums" }
>

となります。

 亡くなっているメンバーを検索するには、フィールドが存在するかしないかを調べるオペレータ「$exists」を使います。trueを返せば存在する、falseを返せば存在しないということになります。

> db.beatles.find({$or:[{part:/Drums/}]},{"_id":0}))
{ "name" : "Paul McCartney", "year_of_birth" : 1942, "month_of_birth" : 6, "date_of_birth" : 18, "part" : "Base,Guiter,Keyboard,Drums" }
{ "name" : "Ringo Starr", "year_of_birth" : 1940, "month_of_birth" : 7, "date_of_birth" : 7, "part" : "Drums" }
{"name" : "Pete Best", "year_of_birth" : 1941, "month_of_birth" : 11, "date_of_birth" : 24, "part" : "Drums" }
>

 メンバーの中で1941年以降に生まれた人だけを抽出しましょう。year_of_birthが1941より大きい、を指定するには「$gte」オペレータを使います。

> db.beatles.find({"year_of_birth" : {$gte: 1941}},{"_id":0}))
{"name" : "George Harrison", "year_of_birth" : 1943, "month_of_birth" : 2, "date_of_birth" : 25, "year_of_death": 2001, "month_of_death" : 11, "date_of_death" : 29, "part" : "Guiter,Sitar,Keyb
oard" }
{"name" : "Paul McCartney", "year_of_birth" : 1942, "month_of_birth" : 6, "date_of_birth" : 18, "part" : "Base,Guiter,Keyboard,Drums" }
{"name" : "Pete Best", "year_of_birth" : 1941, "month_of_birth" : 11, "date_of_birth" : 24, "part" : "Drums" }
>

 ジョージ、ポール、ピートの3人が抽出されました。

 このように、MongoDBは簡単に使うことができます。ぜひ皆さんもお試しあれ!