Firebase Realtime Database for C++ によるデータの取得

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

始める前に

アプリがすでに設定されていて、Get Started ガイドで説明されているようにデータベースにアクセスできることを確認します。

データの取得

Firebase データは、GetValue() へのワンタイム コールまたは FirebaseDatabase 参照で ValueListener にアタッチして取得します。値リスナーはデータの初期状態で 1 回呼び出されます。さらに、データが変更されると、そのたびに再度呼び出されます。

DatabaseReference を取得する

データベースにデータを書き込むには、DatabaseReference のインスタンスが必要です。

    // Get the root reference location of the database.
    firebase::database::DatabaseReference dbref = database->GetReference();

データの 1 回読み取り

GetValue() メソッドを使用して、特定のパスにあるコンテンツの静的スナップショットを 1 回だけ読み取ることができます。タスクの結果には、その場所にあるすべてのデータ(子のデータも含む)を含んでいるスナップショットが含まれます。データが存在しない場合、返されるスナップショットは null です。

  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("Leaders").GetValue();

この時点でリクエストは行われていますが、値を読み取る前に Future が完了するのを待つ必要があります。ゲームは通常ループ内で実行されており、駆動されるコールバックは他のアプリケーションよりも少ないため、完了をポーリングすることが一般的です。

  // In the game loop that polls for the result...

  if (result.status() != firebase::kFutureStatusPending) {
    if (result.status() != firebase::kFutureStatusComplete) {
      LogMessage("ERROR: GetValue() returned an invalid result.");
      // Handle the error...
    } else if (result.error() != firebase::database::kErrorNone) {
      LogMessage("ERROR: GetValue() returned error %d: %s", result.error(),
                 result.error_message());
      // Handle the error...
    } else {
      firebase::database::DataSnapshot snapshot = result.result();
      // Do something with the snapshot...
    }
  }

これは基本的なエラーチェックを示しています。エラーチェックの詳細情報、および結果を使用できるタイミングを判断する方法については、firebase::Future のリファレンスを参照してください。

イベントをリッスンする

データの変更をサブスクライブするリスナーを追加できます。

ValueListener 基本クラス

コールバック 一般的な使用方法
OnValueChanged パスのコンテンツ全体に対する変更の読み取りとリッスンを行います。

OnChildListener 基本クラス

OnChildAdded アイテムのリストを取得します。また、アイテムのリストへの追加をリッスンします。OnChildChanged および OnChildRemoved と組み合わせて使用して、リストに対する変更をモニタリングすることもできます。
OnChildChanged リスト内のアイテムに対する変更がないかリッスンします。OnChildAdded および OnChildRemoved と組み合わせて使用して、リストに対する変更をモニタリングすることもできます。
OnChildRemoved リストから削除されるアイテムがないかリッスンします。OnChildAdded および OnChildChanged と組み合わせて使用して、リストに対する変更をモニタリングすることもできます。
OnChildMoved 並べ替えリストの項目順変更をリッスンします。(現在の order-by メソッドに基づく)項目の順序変更のため、OnChildMoved コールバックは常に OnChildChanged コールバックに後続します。

ValueListener クラス

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

次の例は、データベースからリーダーボードのスコアを取得するゲームを示しています。

  class LeadersValueListener : public firebase::database::ValueListener {
   public:
    void OnValueChanged(
        const firebase::database::DataSnapshot& snapshot) override {
      // Do something with the data in snapshot...
    }
    void OnCancelled(const firebase::database::Error& error_code,
                     const char* error_message) override {
      LogMessage("ERROR: LeadersValueListener canceled: %d: %s", error_code,
                 error_message);
    }
  };

  // Elsewhere in the code...

  LeadersValueListener* listener = new LeadersValueListener();
  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("Leaders").AddValueListener(listener);

Future&ltDataSnapshot&gt の結果には、イベント発生時にデータベース内の指定された場所にあったデータが含まれています。スナップショットの value() を呼び出すと、そのデータを表す Variant が返されます。

この例では、読み取りがキャンセルされたかどうかを確認するために、OnCancelled メソッドもオーバーライドされます。たとえば、Firebase データベースの場所から読み取る権限がクライアントにない場合、読み取りをキャンセルできます。database::Error はエラーが発生した理由を示します。

ChildListener クラス

PushChild() メソッドによる新しい子の追加や、UpdateChildren() メソッドによる子の更新など、ノードの子に対して発生した特定のオペレーションに応じて child イベントがトリガーされます。それぞれのイベントを組み合わせると、データベース内の特定のノードに対する変更をリッスンする場合に役立つことがあります。たとえばゲームでは、以下に示すように、これらのメソッドを組み合わせて使用してゲーム セッションのコメントでのアクティビティをモニタリングできます。

  class SessionCommentsChildListener : public firebase::database::ChildListener {
   public:
    void OnChildAdded(const firebase::database::DataSnapshot& snapshot,
                      const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnChildChanged(const firebase::database::DataSnapshot& snapshot,
                        const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnChildRemoved(
        const firebase::database::DataSnapshot& snapshot) override {
      // Do something with the data in snapshot ...
    }
    void OnChildMoved(const firebase::database::DataSnapshot& snapshot,
                      const char* previous_sibling) override {
      // Do something with the data in snapshot ...
    }
    void OnCancelled(const firebase::database::Error& error_code,
                     const char* error_message) override {
      LogMessage("ERROR: SessionCommentsChildListener canceled: %d: %s",
                 error_code, error_message);
    }
  };

  // elsewhere ....

  SessionCommentsChildListener* listener = new SessionCommentsChildListener();
  firebase::Future<firebase::database::DataSnapshot> result =
    dbRef.GetReference("GameSessionComments").AddChildListener(listener);

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

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

OnChildRemoved コールバックは直接の子が削除されるとトリガーされます。通常は、OnChildAdded および OnChildChanged のコールバックと組み合わせて使用します。コールバックに渡されるスナップショットには、削除された子のデータが含まれています。

OnChildMoved コールバックは、子の再並べ替えを引き起こす更新によって、OnChildChanged の呼び出しが発生するたびにトリガーされます。このイベントは OrderByChild または OrderByValue によるデータの並べ替えで使用されます。

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

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

データを並べ替える

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

メソッド 用途
OrderByChild() 指定した子キーの値で結果を並べ替えます。
OrderByKey() 子キーで結果を並べ替えます。
OrderByValue() 子の値によって結果を並べ替えます。

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

次の例では、スコア順に並べ替えられたスコア リーダーボードをサブスクライブする方法について示しています。

  firebase::database::Query query =
    dbRef.GetReference("Leaders").OrderByChild("score");

  // To get the resulting DataSnapshot either use query.GetValue() and poll the
  // future, or use query.AddValueListener() and register to handle the
  // OnValueChanged callback.

ここでは、ValueListener と組み合わせた場合にクライアントとデータベース内のリーダーボードを同期させる firebase::Query を定義しています。リーダーボードは各エントリのスコアの順に並んでいます。データを効率的に構造化する詳細については、データベースの構造化をご覧ください。

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

データのフィルタリング

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

メソッド 用途
LimitToFirst() 並べ替えられた結果リストの先頭から返すアイテムの最大数を設定します。
LimitToLast() 並べ替えられた結果リストの末尾から返すアイテムの最大数を設定します。
StartAt() 選択した order-by メソッドに応じて、指定したキーまたは値以上のアイテムを返します。
EndAt() 選択した order-by メソッドに応じて、指定したキーまたは値以下のアイテムを返します。
EqualTo() 選択した order-by メソッドに応じて、指定したキーまたは値に等しいアイテムを返します。

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

クエリで一致が 1 つしかない場合でも、スナップショットは 1 つのアイテムだけを含むリストです。

結果の個数を制限する

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

アイテムの変更に応じて、クエリに加わったアイテムに対する OnChildAdded コールバックと、クエリから外れたアイテムに対する OnChildRemoved コールバックを受け取り、合計数が 100 に保たれます。

たとえば、次のコードはリーダーボードからトップのスコアを返します。

  firebase::database::Query query =
    dbRef.GetReference("Leaders").OrderByChild("score").LimitToLast(1);

  // To get the resulting DataSnapshot either use query.GetValue() and poll the
  // future, or use query.AddValueListener() and register to handle the
  // OnValueChanged callback.

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

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() の場合と同じです。

次のステップ