体感!JavaScriptで超速アプリケーション開発 -Meteor完全解説

第9回データベースに関するその他の話題

前回は、MeteorのさまざまなデータベースAPIを説明しました。MongoDBが持つAPIをほぼそのまま利用できるため、非常に柔軟なDB処理を簡潔に実装できます。今回は、これまでに紹介しなかった、データベースに関わる情報をお伝えします。

今回は、前回使用したサンプルをもとに、さまざまな修正を加えていきます。サンプルは以下からダウンロードしてください。

meteor mongo

まずご紹介するのは、Meteorが使用しているMongoDBのデータを直接操作する方法です。Meteorには組み込みでmeteor mongoというコマンドが用意されており、それを使用すると、MongoDBの対話型シェルを呼び出すことができます。

meteor mongoコマンドを使用するには、Meteorが実行中である必要があります。そのため、まずはプロジェクトディレクトリ上でmeteorコマンドをバックグラウンドで実行します。

$ meteor &
[1] 92383
...
Running on: http://localhost:3000/

そして、meteor mongoコマンドを実行してみましょう。⁠>」というプロンプトが表示され、MongoDBのクエリを記述できるようになります。

$ meteor mongo
MongoDB shell version: 2.2.1
connecting to: 127.0.0.1:3002/meteor
> (ここにクエリを記述)

クエリはdb.<コレクション名>.find()のように記述します。dbという変数が、DB内の全てのコレクションを保持しているイメージです。たとえば、前回のサンプルで使用したコレクションに対して、さまざまなクエリを実行してみましょう。

> db.employees.find(); // 全件検索する
{ "name" : "しゅんぺい", "age" : "34", "_id" : "1fd18b19-579b-4e90-8ac1-c2847adbe00d" }
{ "name" : "たえこ", "age" : "33", "_id" : "98a0e2d7-c24f-42ca-9bc6-6e226641d18f" }
{ "name" : "こうたろう", "age" : "4", "_id" : "824724da-81cd-43f7-b2c3-829c426ae001" }
{ "name" : "ちほ", "age" : "2", "_id" : "a4ad5a78-e857-43d3-84b3-092fc8aa10aa" }
> db.employees.find({age: { $gt: 30 }}); // 30歳以上のデータを検索
{ "name" : "しゅんぺい", "age" : 34, "_id" : "e52e6ac7-5dc0-4326-a3f0-1771bd55f09e" }
{ "name" : "たえこ", "age" : 33, "_id" : "f6ae7e0a-51ff-4712-b40a-97d62eeafae9" }

また、クエリだけではなく、更新や削除も行うことができます。

> db.employees.remove({}); //全データを削除
> db.employees.find(); // 全件検索する
> // データがない

MongoDBに対するクエリの記述方法は、ここでは詳しく説明しません。詳細はMongoDBの公式ドキュメントをご覧ください。

セキュリティを向上させる

Meteorのデフォルトでは、サーバ上のすべてのデータがクライアントから参照可能であり、追加・更新・削除といったすべてのデータ操作がクライアントから実行可能です。これは、迅速なプロトタイピングを実現可能にするための、Meteorの初期設定によるものです連載第1回でも申し上げたように、Meteorの哲学は「とにかく早く、簡単に」です⁠⁠。

しかし、この設定は本番運用時には適していません。サーバ上の全データをアクセスしてきた全てのクライアントがキャッシュするのは現実的ではありませんし、簡単なHTTPアクセスでデータを容易に操作されてしまうのも考えものです。

そこで、Meteorを使用して本格的なアプリケーションを構築する際には、まずMeteorの初期設定を変更する必要があります。そのためには、まずMeteorがデフォルトで利用可能としている二つのパッケージ、⁠autopublish」⁠サーバ上の全データを自動的に公開する⁠⁠、⁠insecure」⁠セキュアではない操作を許可する)を無効にする必要があります。

パッケージを削除するためには、meteor remove <パッケージ名>を実行します。

$ meteor remove autopublish insecure

ここでサンプルを再度実行してみましょう。すると、一覧にデータが表示されないばかりではなく、⁠新規」ボタンを押してデータを登録しようとしてもエラーになってしまいます。

サンプル9がエラーに
サンプル9がエラーに

これは、サーバ上のデータが公開されておらず、また、クライアントからのデータ変更が行えなくなったためです。このサンプルを再度正常に動作させるためには、プログラムコードの修正が必要です。

まず、サーバ上のデータを公開するには、Meteor.publish()メソッドを使用します。publish()の第一引数には任意の名称、第二引数にはクライアントに公開するデータを返すコールバック関数を指定します。publish()については次回詳しく説明します。

// (1) 全ての従業員データを公開する
Meteor.publish("all-employees", function () {
  return Employees.find(); // everything
});

また、クライアント側のコードに、公開データをサブスクライブ(購読)するコードを記述します。Meteor.subscribe()の引数に、publish()で使用された名前を指定します。

// (2) 従業員データをサブスクライブする
Meteor.subscribe('all-employees');

このようにコードを修正した時点で実行結果を見てみると、一覧にデータが表示されていることを確認できます。しかし、クライアントからのデータ修正は未だ禁じられているため、データの追加や削除を行うことはできません。

クライアントからのデータ修正を許可(禁止)するには、<コレクション>.allow()<コレクション>.deny()といったメソッドを使用します。これらのメソッドには、insert, update, remove, fetchという名前のプロパティを持つオブジェクトを渡します。このサンプルでは全ての操作を許可するため、以下のようなコードとなります。

// (3) 従業員データに対する全てのデータ操作を許可する
Employees.allow({
    // データの挿入を許可するか
    insert: function(userId, doc) {
        return true;
    },
    // データの更新を許可するか
    update: function(userId, docs, fields, modifier) {
        return true;

    },
    // データの削除を許可するか
    remove: function(userId, docs) {
        return true;
    },
    // クライアントに公開するプロパティを、文字列配列で指定する
    // 全て公開する場合はundefined(もしくは指定しない)
    fetch: undefined
});

insert, update, removeの値となるコールバック関数がtrueを返した場合は、その操作は許可されます。falseまたは関数が何も返さなかった場合は、操作が許可されませんdeny()メソッドの場合はその逆になります⁠⁠。 各コールバック関数が取る引数の説明を以下に記します。

  • userId…その操作を行ったユーザID。ログインしていない場合はnull。データを作成したユーザのIDは、ドキュメントのownerプロパティに格納される。
  • doc(docs)…更新対象のドキュメント。
  • fieldsupdateの場合にのみ使用される。更新対象となるフィールド名の配列
  • modifierupdateの場合にのみ使用される。更新操作を表すオブジェクトmodifier⁠。

以上の変更を加えたサンプル9-1を、以下でダウンロード可能にしておきます。参考にしていただければ幸いです。

まとめ

今回は、これまでに説明しきれなかったデータベース関連の話題について解説しました。これで、Meteorのデータベース操作に関する話題は終わりです。次回はMeteorの先進性を象徴する「リアクティビティ」について、詳しく説明します。

おすすめ記事

記事・ニュース一覧