ウェブでのデータの取得

このドキュメントでは、データの取得に関する基本と、Firebase データの並べ替えとフィルタリングの方法について説明します。

Firebase データは、非同期リスナーを firebase.database.Reference にアタッチして取得します。リスナーはデータの初期状態で 1 回トリガーされます。さらに、データが変更されると、そのたびに再びトリガーされます。

イベントをリッスンする

以下に示す種類のデータ検索イベントをリッスンできます。

イベント 一般的な使用方法
value パスのコンテンツ全体に対する変更の読み取りとリッスンを行います。
child_added アイテムのリストを取得するか、アイテムのリストへの追加がないかリッスンします。child_changedchild_removed と併用して、リストに対する変更をモニタリングすることをおすすめします。
child_changed リスト内のアイテムに対する変更がないかリッスンします。child_addedchild_removed と併用して、リストに対する変更をモニタリングします。
child_removed リストから削除されるアイテムがないかリッスンします。child_addedchild_changed と併用して、リストに対する変更をモニタリングします。
child_moved 並べ替えリストの項目順に変更がないかリッスンします。 child_moved イベントは常に、(現在の order-by メソッドに基づく)並べ替え変更が原因の child_changed イベントに後続します。

イベント リスナーを追加するには、on() メソッドを使用します。

value イベント

value イベントを使用して、特定のパスにあるコンテンツの静的スナップショットを、イベントのときに存在していたとおりに読み取ることができます。このメソッドはリスナーがアタッチされたときに 1 回トリガーされます。さらに、データ(子も含む)が変更されると、そのたびに再びトリガーされます。イベントのコールバックには、その場所にあるすべてのデータ(子のデータも含む)を含んでいるスナップショットが渡されます。データが存在しない場合、返されるスナップショットは null です。

次の例は、データベースから投稿のスターの数を取得するソーシャル ブログ アプリケーションを示しています。

var starCountRef = firebase.database().ref('posts/' + postId + '/starCount');
starCountRef.on('value', function(snapshot) {
  updateStarCount(postElement, snapshot.val());
});

リスナーは snapshot を受信します。これには、イベントのときにデータベース内の指定された場所にあったデータが含まれています。snapshot のデータは val() メソッドを使用して取得できます。

child イベント

push() メソッドによる新しい子の追加や、update() メソッドによる子の更新など、ノードの子に対して発生した特定の操作に応じて、child イベントがトリガーされます。

child_added イベントは通常、Firebase データベース内のアイテムのリストを取得するために使用します。child_added イベントは既存の子ごとに 1 回トリガーされます。さらに、指定されたパスに新しい子が追加されると、そのたびに再びトリガーされます。リスナーには、新しい子のデータを含んでいるスナップショットが渡されます。

子ノードが変更されると、そのたびに child_changed イベントがトリガーされます。この変更には、子ノードの子孫に対する変更も含まれます。このコールバックはアイテムのリストに対する変更に応答するために通常、child_added イベントや child_removed イベントと組み合わせて使用します。イベント リスナーに渡されるスナップショットには、子の更新済みデータが含まれています。

child_removed イベントは直接の子が削除されるとトリガーされます。これは通常、child_added イベントや child_changed イベントと組み合わせて使用します。イベントに渡されるスナップショットには、削除された子のデータが含まれています。

child_moved イベントは、子の再並べ替えが起きる更新によって child_changed イベントがトリガーされると、そのたびにトリガーされます。orderByChild または orderByValue によるデータの並べ替えに使用されます。

それぞれのイベントを組み合わせると、データベース内の特定のノードに対する変更をリッスンする場合に役立つことがあります。たとえば、ソーシャルブログ アプリでは、以下に示すように、これらのメソッドを組み合わせて使用して投稿のコメントでのアクティビティをモニタリングできます。

var commentsRef = firebase.database().ref('post-comments/' + postId);
commentsRef.on('child_added', function(data) {
  addCommentElement(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_changed', function(data) {
  setCommentValues(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_removed', function(data) {
  deleteComment(postElement, data.key);
});

リスナーのデタッチ

コールバックを削除するには、Firebase データベース参照の off() メソッドを呼び出します。

単一のリスナーは、パラメータとしてリスナーを off() に渡すと削除できます。その場所の off() を引数なしで呼び出すと、その場所にあるすべてのリスナーが削除されます。

親リスナーの off() を呼び出しても、その子ノードに登録されているリスナーが自動的に削除されるわけでありません。また、コールバックを削除するために子リスナーの off() も呼び出す必要があります。

データの 1 回読み取り

変更を想定していない UI 要素を初期化するときなど、変更がないかリッスンせずにデータのスナップショットがほしい場合があります。once() メソッドを使用して、このシナリオを簡素化できます。このメソッドは 1 回トリガーされ、その後再びトリガーされることはありません。

これは 1 回読み込む必要があるだけで頻繁な変更やアクティブなリッスンを行うことは想定していないデータに対して有用です。たとえば、以前の例にあるブログアプリでは、このメソッドを使用して、ユーザーが新しい投稿を作成し始めたときにユーザーのプロフィールを読み込んでいます。

var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) {
  var username = snapshot.val().username;
  // ...
});

データの並べ替えとフィルタリング

Realtime Database の Query クラスを使用して、キー、値、または子の値で並べ替えられたデータを取得できます。また、並べ替えられた結果を、特定の個数の結果またはある範囲のキーや値にフィルタリングできます。

データを並べ替える

並べ替えられたデータを取得するには、最初にいずれかの order-by メソッドを指定して、結果の並べ替え方法を決定します。

メソッド 使用方法
orderByChild() 指定した子キーの値で結果を並べ替えます。
orderByKey() 子キーで結果を並べ替えます。
orderByValue() 子の値で結果を並べ替えます。

同時に使用できる order-by メソッドは 1 つだけです。同じクエリで order-by メソッドを複数回呼び出すとエラーがスローされます。

次の例では、スターの数で並べ替えられたユーザーの上位の投稿のリストを取得する方法について示しています。

var myUserId = firebase.auth().currentUser.uid;
var topUserPostsRef = firebase.database().ref('user-posts/' + myUserId).orderByChild('starCount');

ここでは、子リスナーと組み合わせて、ユーザー ID に基づいてデータベース内のパスからクライアントをユーザーの投稿と同期させるクエリを定義しています。ユーザー ID は、それぞれの投稿が受けたスターの数で並べ替えられています。このように ID をインデックス キーとして使用する手法はデータのファンアウトと呼ばれています。詳細については、データベースの構造化をご覧ください。

orderByChild() メソッドの呼び出しでは、結果を並べ替えるための子キーを指定します。ここでは、投稿はそれぞれの投稿の子 "starCount" の値で並べ替えられます。他の種類のデータを並べ替える方法の詳細については、クエリデータが並べ替えられる仕組みをご覧ください。

データのフィルタリング

データをフィルタリングするには、クエリの構築時に、制限メソッドまたは範囲メソッドのいずれかを order-by メソッドと組み合わせることができます。

メソッド 使用方法
limitToFirst() 並べ替えられた結果リストの先頭から返すアイテムの最大数を設定します。
limitToLast() 並べ替えられた結果リストの末尾から返すアイテムの最大数を設定します。
startAt() 選択した order-by メソッドに応じて、指定したキー、値が以上のアイテムを返します。
endAt() 選択した order-by メソッドに応じて、指定したキー、値が以下のアイテムを返します。
equalTo() 選択した order-by メソッドに応じて、指定したキー、値が等しいアイテムを返します。

order-by メソッドとは異なり、複数の制限関数または範囲関数を組み合わせることができます。たとえば、startAt() メソッドと endAt() メソッドを組み合わせて、結果を特定の範囲の値に制限することができます。

結果の個数を制限する

limitToFirst() メソッドと limitToLast() メソッドを使用して、特定のイベントに対して同期する子の最大数を設定できます。たとえば、limitToFirst() を使用して上限 100 を設定した場合は、初期状態で最大 100 個の child_added イベントのみを受け取ります。Firebase データベースに保存されているアイテムが 100 個よりも少ない場合、それぞれのアイテムに対する child_added イベントが発生します。

アイテムの変更に応じて、クエリに加わったアイテムに対する child_added イベントと、クエリから外れたアイテムに対する child_removed イベントを受け取り、合計数が 100 に保たれます。

次の例は、サンプルのブログアプリで全ユーザーの最新 100 件の投稿のリストを取得するクエリを定義する方法を示しています。

var recentPostsRef = firebase.database().ref('posts').limitToLast(100);

この例では、クエリを定義しているだけです。データを実際に同期するには、アタッチされたリスナーが必要です。

キーまたは値によるフィルタリング

startAt()endAt()equalTo() を使用して、クエリ用に任意の始点、終点、同値点を選択できます。これは、データを改ページするときや、特定の値を持つ子があるアイテムを検索するときに役立ちます。

クエリデータが並べ替えられる仕組み

このセクションでは、Query クラスのそれぞれの order-by メソッドでデータがどのように並べ替えられるのかを説明します。

orderByChild

orderByChild() を使用すると、指定した子キーを含むデータは次のように並べ替えられます。

  1. 指定した子キーに null 値を持つ子が最初に来ます。
  2. 指定した子キーに false 値を持つ子が次に来ます。複数の子が値 false を持つ場合、キーの辞書順で並べ替えられます。
  3. 指定した子キーに true 値を持つ子が次に来ます。複数の子が値 true を持つ場合、キーで辞書順に並べ替えられます。
  4. 数値を持つ子が次に来ます。ただし、昇順に並べ替えられます。複数の子が指定した子ノードに同じ数値を持つ場合、キーで並べ替えられます。
  5. 文字列は数値の後に来て、辞書順で昇順に並べ替えられます。複数の子が指定した子ノードに同じ値を持つ場合、キーで辞書順に並べ替えられます。
  6. オブジェクトが最後に来て、キー名の辞書順で昇順に並べ替えられます。

orderByKey

orderByKey() を使用してデータを並べ替えると、キー名で昇順にデータが返されます。

  1. 32 ビット整数として解析できるキーを持つ子が最初に来ます。ただし、昇順に並べ替えられます。
  2. 文字列値をキーとして持つ子が次に来ます。ただし、辞書順で昇順に並べ替えられます。

orderByValue

orderByValue() を使用すると、子がその値で並べ替えられます。並べ替えの条件は、指定した子キーの値の代わりにノードの値が使用されるという点を除いて、orderByChild() の場合と同じです。

次のステップ

フィードバックを送信...