本文將說明擷取資料的基本概念,以及如何排序及篩選 Firebase 資料。
事前準備
如要使用 Realtime Database,您必須先完成下列步驟:
註冊 Unity 專案並設定使用 Firebase。
如果 Unity 專案已使用 Firebase,則表示已為 Firebase 註冊及設定。
如果您沒有 Unity 專案,可以下載應用程式示例。
將 Firebase Unity SDK (具體來說是
FirebaseDatabase.unitypackage
) 新增至 Unity 專案。
請注意,將 Firebase 新增至 Unity 專案時,需要在 Firebase 主控台和您開啟的 Unity 專案中執行任務 (例如,從主控台下載 Firebase 設定檔,然後將其移至 Unity 專案)。
擷取資料
您可以透過一次性的 GetValueAsync() 呼叫,或附加至 FirebaseDatabase
參照的事件,來擷取 Firebase 資料。事件監聽器會針對資料的初始狀態觸發一次,並且在資料變更時會再次觸發。
取得 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
排序的資料。
排序及篩選資料
您可以使用 Realtime Database 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 }
這會定義查詢,當與 valuechanged 事件監聽器結合時,會將用戶端與資料庫中的排行榜同步,並依每個項目的分數排序。如要進一步瞭解如何有效地建構資料,請參閱「建構資料庫」一文。
呼叫 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()
相同,只是會使用節點的值,而非指定子項鍵的值。