使用適用於 C++ 的 Firebase 實時數據庫檢索數據

本文檔介紹了檢索數據以及如何排序和過濾 Firebase 數據的基礎知識。

在你開始之前

確保您已設置應用程序並可以訪問Get Started指南中所述的數據庫。

檢索數據

Firebase 數據通過一次性調用GetValue()或附加到FirebaseDatabase引用上的ValueListener來檢索。值偵聽器在數據的初始狀態下被調用一次,並在數據發生變化時再次調用。

獲取數據庫參考

要將數據寫入數據庫,您需要一個DatabaseReference實例:

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

讀取一次數據

您可以使用GetValue()方法讀取給定路徑中內容的靜態快照一次。任務結果將包含一個快照,其中包含該位置的所有數據,包括子數據。如果沒有數據,則返回的快照為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檢索項目列表或偵聽項目列表的添加內容。建議與OnChildChangedOnChildRemoved一起使用來監視列表的更改。
OnChildChanged監聽列表中項目的更改。與OnChildAddedOnChildRemoved一起使用來監視列表的更改。
OnChildRemoved偵聽從列表中刪除的項目。與OnChildAddedOnChildChanged一起使用來監視列表的更改。
OnChildMoved偵聽有序列表中項目順序的更改。由於項目的順序發生變化(基於當前的排序方式), OnChildMoved回調始終遵循OnChildChanged回調。

值監聽器類

您可以使用OnValueChanged回調來訂閱給定路徑中內容的更改。當附加偵聽器時會觸發此回調一次,每次數據(包括子項)發生更改時都會觸發一次。向回調傳遞包含該位置的所有數據(包括子數據)的快照。如果沒有數據,則返回的快照為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&ltDataSnaphot&gt結果包含事件發生時數據庫中指定位置的數據。對快照調用value()返回表示數據的Variant

在此示例中,還重寫了OnCancelled方法以查看讀取是否被取消。例如,如果客戶端沒有從 Firebase 數據庫位置讀取的權限,則可以取消讀取。 database::Error將指示發生故障的原因。

子監聽器類

子事件是為了響應節點子節點發生的特定操作而觸發的,這些操作例如通過PushChild()方法添加的新子節點或通過UpdateChildren()方法更新的子節點。這些中的每一個都可以用於偵聽數據庫中特定節點的更改。例如,遊戲可能會同時使用這些方法來監視遊戲會話評論中的活動,如下所示:

  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回調為每個現有子項調用一次,然後每次將新子項添加到指定路徑時再次調用。偵聽器會收到包含新子項數據的快照。

每當修改子節點時都會調用OnChildChanged回調。這包括對子節點的後代的任何修改。它通常與OnChildAddedOnChildRemoved調用結合使用,以響應項目列表的更改。傳遞給偵聽器的快照包含子級的更新數據。

當直接子項被刪除時,會觸發OnChildRemoved回調。它通常與OnChildAddedOnChildChanged回調結合使用。傳遞給回調的快照包含已刪除子項的數據。

每當因導致子項重新排序的更新而引發OnChildMoved調用時,都會觸發OnChildChanged回調。它與通過OrderByChildOrderByValue排序的數據一起使用。

排序和過濾數據

您可以使用實時數據庫Query類來檢索按鍵、按值或按子值排序的數據。您還可以將排序結果過濾為特定數量的結果或一系列鍵或值。

對數據進行排序

要檢索排序的數據,請首先指定排序方法之一來確定結果的排序方式:

方法用法
OrderByChild()按指定子鍵的值對結果進行排序。
OrderByKey()按子鍵對結果進行排序。
OrderByValue()按子值對結果進行排序。

您一次只能使用一種排序方式。在同一查詢中多次調用 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.

這定義了一個firebase::Query ,當與ValueListener結合使用時,會將客戶端與數據庫中的排行榜同步,並按每個條目的分數排序。您可以在構建數據庫中閱讀有關有效構建數據的更多信息。

OrderByChild()方法的調用指定用於對結果進行排序的子鍵。在這種情況下,結果按每個子項中的"score"值排序。有關其他數據類型如何排序的詳細信息,請參閱查詢數據如何排序

過濾數據

要過濾數據,您可以在構造查詢時將任何限製或範圍方法與排序方法結合起來。

方法用法
LimitToFirst()設置從有序結果列表開頭返回的最大項目數。
LimitToLast()設置從有序結果列表末尾返回的最大項目數。
StartAt()根據所選的排序方法,返回大於或等於指定鍵或值的項目。
EndAt()根據所選的排序方法,返回小於或等於指定鍵或值的項目。
EqualTo()根據所選的排序方法,返回等於指定鍵或值的項目。

與排序方法不同,您可以組合多個限製或範圍函數。例如,您可以組合StartAt()EndAt()方法將結果限制為指定的值範圍。

即使查詢只有一個匹配項,快照仍然是一個列表;它只包含一個項目。

限制結果數量

您可以使用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()中的相同,只是使用節點的值而不是指定子鍵的值。

下一步