本文說明擷取資料的基本概念,以及如何排序及篩選 Firebase 資料。
事前準備
使用即時資料庫前,您必須先完成以下事項:
註冊 Unity 專案,並將其設定為使用 Firebase。
如果您的 Unity 專案已使用 Firebase,表示該專案已完成註冊並設定 Firebase。
如果您沒有 Unity 專案,可以下載範例應用程式。
在 Unity 專案中新增 Firebase Unity SDK (尤其是
FirebaseDatabase.unitypackage
)。
請注意,將 Firebase 新增至 Unity 專案涉及到 Firebase 主控台和開放式 Unity 專案中的工作 (例如從主控台下載 Firebase 設定檔,再移至 Unity 專案)。
正在擷取資料
系統會擷取 Firebase 資料,方法有兩種:一次呼叫 GetValueAsync(),或是附加至 FirebaseDatabase
參照的事件。系統會針對資料的初始狀態呼叫一次事件監聽器,並在資料變更時再次呼叫。
取得 DatabaseReference
如要從資料庫讀取資料,您需要 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
| 擷取項目清單,或監聽附加項目清單。
建議搭配 ChildChanged 和 ChildRemoved 使用,監控清單變更。 |
ChildChanged |
監聽清單中項目的變更。使用 ChildAdded 和 ChildRemoved 即可監控清單變更。 |
ChildRemoved |
監聽已從清單中移除的項目。使用 ChildAdded 和 ChildChanged 即可監控清單變更。 |
ChildMoved |
監聽已排序清單中項目順序的變更。
ChildMoved 事件一律會遵循導致項目順序變更的 ChildChanged 事件 (以目前的排序方式為準)。 |
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
事件。這也包括對子節點子系所做的任何修改。它通常會與 ChildAdded
和 ChildRemoved
事件搭配使用,以回應項目清單的變更。傳遞至事件監聽器的快照會包含子項的更新資料。
移除即時子項時,會觸發 ChildRemoved
事件。通常與 ChildAdded
和 ChildChanged
回呼搭配使用。傳遞至事件回呼的快照會包含已移除的子項資料。
每當更新引發 ChildChanged
事件,進而重新排序子項時,就會觸發 ChildMoved
事件。可與以 OrderByChild
或 OrderByValue
排序的資料搭配使用。
排序及篩選資料
您可以使用即時資料庫 Query
類別,擷取依鍵、值或子項值排序的資料。您也可以篩選排序結果,以達到特定結果數量、鍵/值範圍。
排序資料
如要擷取經過排序的資料,請先指定一種依順序排序的方法來決定結果的排序方式:
方式 | 用量 |
---|---|
OrderByChild() |
按照指定子鍵的值排序結果。 |
OrderByKey()
| 按子項鍵排序結果。 |
OrderByValue() |
按照子項值排序結果。 |
一次只能使用「一個」排序方法。在同一查詢中多次呼叫依順序的方法呼叫會擲回錯誤。
以下範例說明如何在依分數排序的得分排行榜上進行訂閱。
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 }
這會定義一項查詢,與值變更事件監聽器搭配使用時,系統會依每個項目的分數排序用戶端與資料庫中的排行榜。如要進一步瞭解如何有效率地建構資料,請參閱建立資料庫結構。
OrderByChild()
方法的呼叫會指定子項鍵,依結果排序結果。在這種情況下,結果會按照每個子項中的 "score"
值排序。如要進一步瞭解其他資料類型的排序方式,請參閱查詢資料的排序方式。
篩選資料
如要篩選資料,您可以在建構查詢時,將任何限製或範圍方法與排序方法結合。
方式 | 用量 |
---|---|
LimitToFirst() |
設定要從已排序結果清單開頭傳回的項目數量上限。 |
LimitToLast() |
設定從已排序結果清單結尾傳回的項目數量上限。 |
StartAt() |
依據所選的順序,傳回大於或等於指定鍵或值的項目。 |
EndAt() |
依據所選的順序,傳回小於或等於指定鍵或值的項目。 |
EqualTo() |
根據所選順序,傳回與指定鍵或值相等的項目。 |
有別於依序執行排序的方式,您可以合併多個限製或範圍函式。舉例來說,您可以結合 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
類別中各個排序方法如何排序資料。
OrderByChild
使用 OrderByChild()
時,包含指定子項鍵的資料會按照以下順序排序:
- 針對指定子項金鑰,具有
null
值的子項會先列出。 - 指定子項金鑰值為
false
的子項接著會顯示。如果多個子項的值為false
,則這些子項的值會按照鍵字母順序排序。 - 指定子項金鑰值為
true
的子項接著會顯示。如果多個子項的值為true
,就會按照鍵的字母順序排序。 - 含有數值的子項接著會以遞增順序排序。如果指定的子節點有多個子項具有相同數值,系統會按照索引鍵排序。
- 字串是由數字後方,並按遞增順序排列。如果指定的子節點有多個子項的值相同,就會按照鍵的字母順序排列。
- 物件在最後,且依索引鍵順序排列,以遞增順序排列。
OrderByKey
使用 OrderByKey()
排序資料時,系統會依鍵以遞增順序傳回資料。
- 如果子項的索引鍵可剖析為 32 位元整數,其內容會先以遞增順序排序。
- 具有字串值做為索引鍵的下一個子項,並依字母順序遞增排序。
OrderByValue
使用 OrderByValue()
時,子項會按照值的順序排列。排序條件與 OrderByChild()
相同,但會使用節點的值而非指定子項鍵的值。