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

第8回 MeteorのデータベースAPI

この記事を読むのに必要な時間:およそ 4 分

前回は,Meteorのデータベースアーキテクチャを説明しました。Meteorがサーバデータをクライアントにキャッシュすることで,クライアントでもサーバでも同様のAPIを用いることができるため,クライアントとサーバのコード共有が最大限に促進されます。

では,今回はMeteorのデータベースAPIを紹介していきたいと思います。ただし字数の都合上,全てのAPIを紹介することはできません。完全なリストはMeteorの公式ドキュメントを参照してください。

また,MeteorのデータベースAPIはMongoDBを理解していると,より理解が促進されます。ちょうど,gihyo.jpでも連載記事があるようなので,参照することをお勧めします。

また,前回使用したサンプルに機能を追加して,データの追加・更新・削除を行えるようにしたサンプルを用意しました。

図1 サンプル8-1

図1 サンプル8-1

上部のフォームに値を入力して「追加」ボタンを押すと,データベースに値が追加されます。一覧のチェックボックスを選択すると,上部のフォームに値が読み出されます。そのまま値を修正して更新を行うことができます。また,チェックした行のレコードをまとめて削除することができます。

こちらのサンプルは,コード量が多少かさんでしまったので,サンプルの全文は掲載しません。以下からダウンロード可能にしておきますので,必要に応じて参照してください。

サンプル8-1(sample8-1.zip)のダウンロードはこちらから

コレクション

前回もご説明した通り,データベースに格納するオブジェクトの集まりを「コレクション」と呼びます。一つのコレクションには任意のJavaScriptオブジェクトを格納できますが,通常,同様のプロパティを持つ同じ型のオブジェクトを格納します。また,MongoDBではコレクションに格納するオブジェクトのことを「ドキュメント」と呼び表しますので,以下それに従います。

new Meteor.Collection(name, options)

コレクションを生成するためのコンストラクタです。第一引数にはコレクションの名前を表す文字列,第二引数にはオプションを指定します(オプションについては,ここでは説明しません)⁠nameを省略すると,サーバ・クライアント間での同期が行われないコレクションとなります。

サンプルにおいては,従業員データを格納するためのコレクションをemployeesという名前で作成しています。

// (1) コレクションの生成
var Employees = new Meteor.Collection('employees');

find(selector, options)

コレクション内で,条件に合致するドキュメントを検索して返します。検索条件は,第一引数のselectorで指定します。たとえば,ID_idプロパティ)の値が一致することを表す条件は以下のようになります。

Employees.find({ _id: '...' });

複数のプロパティが一致する条件を指定することもできます。

Employees.find({ name: '...', age: '...' });

また,値の大小に基づく比較条件や条件の否定(NOT)なども行うことができます。

// ageの値が10以上
Employees.find({ age: { $gt: 10 } });

// nameの値が'しゅんぺい'以外のレコード
Employees.find({ name: { $not: 'しゅんぺい' } });

検索条件を指定しない(すべて取得する)場合には,空のオブジェクトを指定します。

Employees.find({});

その他にもたくさんの条件指定方法があります。詳しくはMongoDBの公式リファレンスを参照してください。

第二引数には,以下の様なプロパティを持つJavaScriptオブジェクトを指定します。

  • sort…ソートの指定。ソートするプロパティの順序を配列で指定します。

    // aの昇順,bの降順
    [["a", "asc"], ["b", "desc"]]
    // 上と同様。昇順の場合はプロパティ名の指定のみでOK
    ["a", ["b", "desc"]]
    
  • skip…結果をスキップする件数

  • limit…最大の取得結果数

  • fields…結果に含めるフィールド(サーバ上でのみ有効)⁠結果に含めるプロパティには1を,含めないプロパティには0を指定します。

    // ageプロパティを除外する
    Employees.find({}, {fields: {age: 0}})
    
  • reactive…結果をリアクティブとするかどうか。デフォルトはtrue(リアクティビティについては,後の連載記事をお待ちください)

サンプルにおいては,テンプレート内の変数employeesの値として,関数の戻り値に指定しています。

    // テンプレート内のemployeesという変数の値を返す
    Template.employeeList.employees = function() {
        // (2) コレクション内の全データを返す
        var cursor = Employees.find();
        return cursor;
    };

返却されるオブジェクトは,検索結果を辿ることのできるカーソルMeteor.Collection.Cursorです。カーソルには以下のようなメソッドが定義されています。

  • forEach(callback)…先頭から順にドキュメントを処理します。以下のように使用します。

    var cursor = Employees.find();
    // 一件ずつ処理する
    cursor.forEach(function(employee) {
      ...
    });
    
  • map(callback)…カーソルの内容から,新たな配列を生成します。配列の要素は,コールバック引数の戻り値で構成されます。

    // 従業員IDのみで構成される
    var idList = cursor.map(function(employee) {
      return employee._id;
    });
    
  • fetch()…カーソルから全てのデータを読み込み,配列を返します。

  • count()…検索結果の総数を返します。

  • rewind()…カーソルを初期状態に戻します。

  • observe(callbacks)…カーソルの状態を監視します。以下の利用法を見てください。

    // (3) カーソルの状態を監視してログを残す
    cursor.observe({
        // 検索結果が増やされた
        added: function(document, beforeIndex) {
            console.log('added(追加された位置:' + beforeIndex + ')');
        },
        // 検索結果が変更された
        changed: function(newDocument, atIndex, oldDocument) {
            console.log('changed(位置:' + atIndex + ')');
        },
        // 検索結果内でオブジェクトのインデックスが変わった
        moved: function(document, oldIndex, newIndex) {
            console.log('moved(前の位置:' + oldIndex + ' 後の位置:' + newIndex + ')');
        },
        // 検索結果からオブジェクトが減った
        removed: function(oldDocument, atIndex) {
            console.log('removed(位置:' + atIndex + ')');
        }
    });
    

著者プロフィール

白石俊平(しらいししゅんぺい)

株式会社オープンウェブ・テクノロジー代表取締役

HTML5開発者コミュニティhtml5j.org管理人

HTML5とか勉強会主催

Web先端技術味見部 部長

読書するエンジニアの会主催

しろうと哲学部 部長

Google API Expert(HTML5)

Microsoft Most Valuable Professional 2010, 2011(Internet Explorer)

コメント

コメントの記入