Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

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

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

在你開始之前

請確保您已設置您的應用程序和覆蓋在可以訪問數據庫Get Started指南。

檢索數據

火力數據由任一時間調用檢索GetValue()或附連到ValueListener上的FirebaseDatabase參考。值偵聽器為數據的初始狀態調用一次,並在數據更改時再次調用。

獲取數據庫參考

為了將數據寫入到數據庫中,你需要的實例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...
    }
  }

這顯示一些基本的錯誤檢查,看到火力::未來的更多信息,錯誤檢查的參考,以及如何確定當結果已就緒。

監聽事件

您可以添加偵聽器以訂閱數據更改:

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將表明發生故障的原因。

ChildListener 類

兒童事件響應碰巧從操作節點的兒童的具體操作引發的,如通過添加一個新的子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回調通常用於檢索的數據庫火力地堡的項目清單。該OnChildAdded每一個新的子項被添加到指定的路徑時回調被調用一次為每個現有子,然後再次。偵聽器被傳遞一個包含新孩子數據的快照。

OnChildChanged回調被稱為子節點隨時修改。這包括對子節點後代的任何修改。它通常與配合使用OnChildAddedOnChildRemoved電話回應變更的項目列表。傳遞給偵聽器的快照包含子項的更新數據。

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

OnChildMoved每當觸發回調OnChildChanged調用是導致重新排序子的更新提高。它的使用將是有序的數據OrderByChildOrderByValue

排序和過濾數據

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

排序數據

要檢索已排序的數據,首先指定一種 order-by 方法來確定結果的排序方式:

方法用法
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"在每個孩子的價值。有關其它數據類型如何排序的詳細信息,請參閱查詢數據是如何排序

過濾數據

要過濾數據,您可以在構建查詢時將任何限製或範圍方法與 order-by 方法結合使用。

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

與 order-by 方法不同,您可以組合多個限製或範圍函數。例如,你可以結合StartAt()EndAt()方法來限制的結果,值的指定範圍。

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

限制結果數量

您可以使用LimitToFirst()LimitToLast()方法來設置兒童被同步對於一個給定的回調的最大數量。例如,如果你使用LimitToFirst()設置的100個限度,你最初只獲得高達100 OnChildAdded回調。如果您有存儲在您的火力地堡數據庫,少於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類。

OrderByChild

當使用OrderByChild()包含指定的子鍵如下排序的數據:

  1. 與兒童null的指定子鍵值是第一位的。
  2. 用價值孩子false的指定子鍵來下。如果有多個孩子的價值false ,它是按照字典序的關鍵。
  3. 用價值孩子true用於指定的子鍵來下。如果有多個孩子的價值true ,它們是由鍵按字典順序排序。
  4. 接下來是帶有數值的孩子,按升序排序。如果指定子節點的多個子節點具有相同的數值,則它們按鍵排序。
  5. 字符串在數字之後,按字典順序升序排列。如果指定子節點的多個子節點具有相同的值,則它們按字典順序按關鍵字排序。
  6. 對象排在最後,並按字典順序按鍵升序排序。

OrderByKey

當使用OrderByKey()對數據進行排序,數據在由鍵升序返回。

  1. 具有可以解析為 32 位整數的鍵的子項首先出現,按升序排序。
  2. 接下來是以字符串值作為鍵的子項,按字典順序升序排列。

OrderByValue

當使用OrderByValue()孩子們通過自己的價值排序。排序標準是一樣OrderByChild()除了節點的值被用來代替一個指定的子密鑰的值。

下一步