檢索數據

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

在你開始之前

在使用實時數據庫之前,您需要:

  • 註冊您的 Unity 項目並將其配置為使用 Firebase。

    • 如果您的 Unity 項目已經使用 Firebase,那麼它已經為 Firebase 註冊和配置。

    • 如果您沒有 Unity 項目,可以下載示例應用程序

  • Firebase Unity SDK (特別是FirebaseDatabase.unitypackage )添加到您的 Unity 項目中。

請注意,將 Firebase 添加到您的 Unity 項目涉及Firebase 控制台和打開的 Unity 項目中的任務(例如,您從控制台下載 Firebase 配置文件,然後將它們移動到您的 Unity 項目中)。

檢索數據

Firebase 數據通過一次性調用 GetValueAsync() 或附加到FirebaseDatabase引用上的事件來檢索。事件偵聽器在數據的初始狀態中調用一次,並且在數據更改時再次調用。

獲取數據庫引用

要從數據庫中讀取數據,您需要一個DatabaseReference實例:

using Firebase;
using Firebase.Database;
using Firebase.Extensions.TaskExtension; // for ContinueWithOnMainThread

public class MyScript: MonoBehaviour {
  void Start() {
    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

讀取數據一次

您可以使用GetValueAsync方法一次讀取給定路徑中內容的靜態快照。任務結果將包含一個快照,其中包含該位置的所有數據,包括子數據。如果沒有數據,則返回的快照為null

    FirebaseDatabase.DefaultInstance
      .GetReference("Leaders")
      .GetValueAsync().ContinueWithOnMainThread(task => {
        if (task.IsFaulted) {
          // Handle the error...
        }
        else if (task.IsCompleted) {
          DataSnapshot snapshot = task.Result;
          // Do something with snapshot...
        }
      });

監聽事件

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

事件典型用法
ValueChanged閱讀並監聽路徑全部內容的變化。
ChildAdded檢索項目列表或監聽項目列表的添加。建議與ChildChangedChildRemoved一起使用來監控列表的更改。
ChildChanged監聽列表中項目的更改。與ChildAddedChildRemoved一起使用以監視對列表的更改。
ChildRemoved偵聽從列表中刪除的項目。與ChildAddedChildChanged一起使用以監視對列表的更改。
ChildMoved監聽有序列表中項目順序的變化。 ChildMoved事件始終跟隨導致項目順序更改的ChildChanged事件(基於您當前的 order-by 方法)。

ValueChanged 事件

您可以使用ValueChanged事件來訂閱給定路徑的內容更改。此事件在附加偵聽器時觸發一次,並且在每次數據(包括子項)發生更改時再次觸發。事件回調被傳遞一個快照,其中包含該位置的所有數據,包括子數據。如果沒有數據,則返回的快照為null

以下示例演示了一個從數據庫中檢索排行榜分數的遊戲:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

ValueChangedEventArgs包含一個DataSnapshot ,其中包含事件發生時數據庫中指定位置的數據。對快照調用Value會返回一個表示數據的Dictionary<string, object> 。如果該位置不存在數據,則調用Value返回null

在此示例中,還會檢查args.DatabaseError以查看讀取是否被取消。例如,如果客戶端無權從 Firebase 數據庫位置讀取,則可以取消讀取。 DatabaseError將指示失敗發生的原因。

您可以稍後使用具有相同路徑的任何DatabaseReference取消訂閱該事件。 DatabaseReference實例是短暫的,可以被認為是訪問任何路徑和查詢的一種方式。

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged -= HandleValueChanged; // unsubscribe from ValueChanged.
    }

兒童活動

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

      var ref = FirebaseDatabase.DefaultInstance
      .GetReference("GameSessionComments");

      ref.ChildAdded += HandleChildAdded;
      ref.ChildChanged += HandleChildChanged;
      ref.ChildRemoved += HandleChildRemoved;
      ref.ChildMoved += HandleChildMoved;
    }

    void HandleChildAdded(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildChanged(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildRemoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildMoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

ChildAdded事件通常用於檢索 Firebase 數據庫中的項目列表。 ChildAdded事件為每個現有的孩子引發一次,然後每次將新的孩子添加到指定的路徑時再次引發。偵聽器被傳遞一個包含新孩子數據的快照。

任何時候修改子節點都會引發ChildChanged事件。這包括對子節點後代的任何修改。它通常與ChildAddedChildRemoved事件結合使用,以響應對項目列表的更改。傳遞給事件偵聽器的快照包含子節點的更新數據。

ChildRemoved事件在刪除直接子項時觸發。它通常與ChildAddedChildChanged回調一起使用。傳遞給事件回調的快照包含已刪除子項的數據。

每當導致子項重新排序的更新引發ChildMoved事件時,就會觸發ChildChanged事件。它與使用OrderByChildOrderByValue排序的數據一起使用。

排序和過濾數據

您可以使用實時數據庫Query類來檢索按鍵、按值或按子值排序的數據。您還可以將排序結果篩選為特定數量的結果或鍵或值範圍。

排序數據

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

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

您一次只能使用一種排序方法。在同一個查詢中多次調用 order-by 方法會引發錯誤。

以下示例演示瞭如何訂閱按分數排序的分數排行榜。

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

這定義了一個查詢,當與valuechanged 事件偵聽器結合使用時,將客戶端與數據庫中的排行榜同步,按每個條目的分數排序。您可以在Structure Your Database中閱讀有關有效構建數據的更多信息。

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

過濾數據

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

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

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

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

限制結果數量

您可以使用LimitToFirst()LimitToLast()方法為給定的回調設置要同步的最大子節點數。例如,如果您使用LimitToFirst()將限制設置為 100,您最初最多只能收到 100 個ChildAdded回調。如果您的 Firebase 數據庫中存儲的項目少於 100 個,則會為每個項目觸發ChildAdded回調。

隨著項目的變化,您會收到進入查詢的項目的ChildAdded回調和退出查詢的項目的ChildRemoved回調,因此總數保持在 100。

例如,下面的代碼返回排行榜的最高分:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score").LimitToLast(1)
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

按鍵或值過濾

您可以使用StartAt()EndAt()EqualTo()來選擇查詢的任意起點、終點和等價點。這對於對數據進行分頁或查找具有特定值的子項非常有用。

查詢數據如何排序

本節說明如何按Query類中的每個 order-by 方法對數據進行排序。

OrderByChild

使用OrderByChild()時,包含指定子鍵的數據按如下順序排列:

  1. 具有指定子鍵的null值的子項首先出現。
  2. 接下來是指定子鍵的值為false的子項。如果多個孩子的值為false ,則它們按字典順序鍵排序。
  3. 接下來是指定子鍵的值為true的子項。如果多個孩子的值為true ,則它們按字典順序鍵排序。
  4. 接下來是具有數值的子項,按升序排列。如果指定子節點的多個子節點的數值相同,則按key排序。
  5. 字符串在數字之後,並按字典順序升序排序。如果指定子節點的多個子節點具有相同的值,則它們按字典順序鍵排序。
  6. 對象排在最後,並按關鍵字按字典順序升序排序。

OrderByKey

使用OrderByKey()對數據進行排序時,數據按 key 升序返回。

  1. 具有可以被解析為 32 位整數的鍵的子項排在最前面,按升序排序。
  2. 以字符串值作為鍵的子項緊隨其後,按字典順序升序排序。

OrderByValue

使用OrderByValue()時,子項按其值排序。排序標準與OrderByChild()中的相同,只是使用節點的值而不是指定子鍵的值。