取得資料庫參照
如要從資料庫讀取或寫入資料,您需要 DatabaseReference
的執行個體:
DatabaseReference ref = FirebaseDatabase.instance.ref();
讀取及寫入清單
將資料附加至資料清單
使用 push()
方法,將資料附加至多用戶端應用程式中的清單。每次在指定的 Firebase 參照資料中新增子項時,push()
方法都會產生專屬索引鍵。只要在清單中的每個新元素使用這些自動產生的鍵,多個用戶端就能同時將子項新增至相同位置,而不會發生寫入衝突。push()
產生的專屬索引會以時間戳記為依據,因此清單項目會自動依時間順序排序。
您可以參照 push()
方法傳回新資料的參照,取得子項自動產生的鍵值,或為子項設定資料。push()
參照的 .key
屬性包含自動產生的金鑰。
您可以使用這些自動產生的鍵,簡化資料結構的平坦化作業。詳情請參閱資料分支範例。
舉例來說,push()
可用於在社群應用程式中的貼文清單中新增貼文:
DatabaseReference postListRef = FirebaseDatabase.instance.ref("posts");
DatabaseReference newPostRef = postListRef.push();
newPostRef.set({
// ...
});
監聽子項事件
子項事件會在特定作業發生時觸發,例如透過 push()
方法新增子項,或是透過 update()
方法更新子項。
事件 | 常見用途 |
---|---|
onChildAdded |
擷取項目清單,或監聽項目清單的新增項目。每個現有子項都會觸發此事件一次,之後每次將新子項新增至指定路徑時,就會再次觸發此事件。事件監聽器傳遞了含有新子項資料的快照。 |
onChildChanged |
監聽清單中項目的變更。 每次修改子節點時,系統都會觸發這項事件。包括對子節點後代所做的任何修改。傳遞至事件監聽器的快照包含子項的更新資料。 |
onChildRemoved |
監聽已從清單中移除的項目。當移除直接子項時,系統會觸發這項事件。傳遞至回呼區塊的快照包含已移除子項的資料。 |
onChildMoved |
監聽已排序清單中項目順序的變更。 onChildMoved 事件一律會在導致項目順序變更的 onChildChanged 事件之後發生 (依據目前的排序方法)。 |
這些事件都很實用,可用於監聽資料庫中特定節點的變更。舉例來說,社群網站的部落格應用程式可能會同時使用這些方法,監控貼文留言中的活動,如下所示:
final commentsRef = FirebaseDatabase.instance.ref("post-comments/$postId");
commentsRef.onChildAdded.listen((event) {
// A new comment has been added, so add it to the displayed list.
});
commentsRef.onChildChanged.listen((event) {
// A comment has changed; use the key to determine if we are displaying this
// comment and if so displayed the changed comment.
});
commentsRef.onChildRemoved.listen((event) {
// A comment has been removed; use the key to determine if we are displaying
// this comment and if so remove it.
});
監聽價值事件
雖然建議您監聽子項事件來讀取資料清單,但在某些情況下,監聽清單參照的值事件也相當實用。
將 value
事件監聽器附加至資料清單,系統就會將整個資料清單做為單一快照傳回,您可以循環處理該快照來存取個別子項。
即使查詢只符合一個項目,快照仍是清單,只是只包含一個項目。如要存取該項目,您需要循環處理結果:
myTopPostsQuery.onValue.listen((event) {
for (final child in event.snapshot.children) {
// Handle the post.
}
}, onError: (error) {
// Error.
});
如要擷取清單的所有子項,而非監聽其他子項新增事件,這類模式就很實用。
排序及篩選資料
您可以使用 Query
類別,擷取依鍵、值或子項值排序的資料。您也可以篩選排序結果,以達到特定結果數量或鍵/值範圍。
排序資料
如要擷取已排序的資料,請先指定其中一種排序方法,以決定結果的排序方式:
方法 | 用量 |
---|---|
orderByChild() |
按指定子項鍵或巢狀子路徑的值排序結果。 |
orderByKey() |
依子項索引鍵排序結果。 |
orderByValue() |
依子項值排序結果。 |
您一次只能使用 一個 排序方法。在同一項查詢中多次呼叫排序方法會擲回錯誤。
以下範例說明如何擷取使用者的熱門貼文清單,並依星號數量排序:
final myUserId = FirebaseAuth.instance.currentUser?.uid;
final topUserPostsRef = FirebaseDatabase.instance
.ref("user-posts/$myUserId")
.orderByChild("starCount");
這會定義查詢,當與子項事件監聽器結合時,會根據使用者 ID 將用戶端與使用者的資料庫路徑中的貼文同步,並依每則貼文收到的星號數排序。這種使用 ID 做為索引鍵的技術稱為資料扇形展開,您可以在「建立資料庫結構」一文中進一步瞭解。
呼叫 orderByChild()
方法時,請指定子項鍵來排序結果。在這種情況下,系統會依據各個 "starCount"
子項的值排序貼文。如果資料如下所示,查詢也可以依巢狀子項排序:
"posts": {
"ts-functions": {
"metrics": {
"views" : 1200000,
"likes" : 251000,
"shares": 1200,
},
"title" : "Why you should use TypeScript for writing Cloud Functions",
"author": "Doug",
},
"android-arch-3": {
"metrics": {
"views" : 900000,
"likes" : 117000,
"shares": 144,
},
"title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
"author": "Doug",
}
},
在這種情況下,我們可以透過在 orderByChild()
呼叫中指定巢狀子項的相對路徑,依據巢狀於 metrics
鍵下的值排序清單元素。
final mostViewedPosts =
FirebaseDatabase.instance.ref('posts').orderByChild('metrics/views');
如要進一步瞭解其他資料類型的排序方式,請參閱「查詢資料的排序方式」。
篩選資料
如要篩選資料,您可以在建構查詢時,將任何限制或範圍方法與排序方法結合。
方法 | 用量 |
---|---|
limitToFirst() |
設定從排序結果清單開頭傳回的項目數量上限。 |
limitToLast() |
設定從已排序結果清單結尾傳回的項目數量上限。 |
startAt() |
傳回大於或等於指定鍵或值的項目,具體取決於所選排序方法。 |
startAfter() |
視所選方法而定,傳回大於指定鍵或值的項目。 |
endAt() |
依據所選順序,傳回小於或等於指定鍵或值的項目。 |
endBefore() |
傳回的項目小於指定的鍵或值,具體取決於所選排序方法。 |
equalTo() |
傳回等於指定鍵或值的項目,具體取決於所選排序方法。 |
與排序方法不同,您可以結合多個限制或範圍函式。舉例來說,您可以結合 startAt()
和 endAt()
方法,將結果限制為指定範圍內的值。
限制結果數量
您可以使用 limitToFirst()
和 limitToLast()
方法,設定要針對特定事件同步處理的子項數量上限。舉例來說,如果您使用 limitToFirst()
將限制設為 100,則一開始只會收到 100 個 onChildAdded
事件。如果 Firebase 資料庫中儲存的項目少於 100 個,系統會為每個項目觸發 onChildAdded
事件。
隨著項目變更,您會收到 onChildAdded
事件 (針對進入查詢的項目) 和 onChildRemoved
事件 (針對退出查詢的項目),讓總數維持在 100。
以下範例說明如何透過查詢,擷取所有使用者最近 100 篇貼文的清單:
final recentPostsRef = FirebaseDatabase.instance.ref('posts').limitToLast(100);
這個範例僅定義查詢,如要實際同步處理資料,該查詢需要有附加的事件監聽器。
依鍵或值篩選
您可以使用 startAt()
、startAfter()
、endAt()
、endBefore()
和 equalTo()
為查詢選擇任意起始、結束和等價點。這對於分頁資料或尋找具有特定值的子項項目很有幫助。
查詢資料的排序方式
本節說明如何依據 Query
類別中的各個排序方法排序資料。
orderByChild
使用 orderByChild()
時,包含指定子項鍵的資料會按照以下順序排序:
- 針對指定子項金鑰,具有
null
值的子項會先列出。 - 接著是指定子項鍵的值為
false
的子項。如果有多個子項的值為false
,系統會依鍵值排序。 - 接著是指定子項鍵的值為
true
的子項。如果有多個子項的值為true
,系統會依字典順序依鍵排序。 - 含有數值的子項接著會以遞增順序排序。如果多個子項的數值與指定子項節點相同,系統會依鍵值排序。
- 字串會排在數字之後,並依字典順序遞增排列。如果多個子項的值與指定子節點相同,系統會依字典順序排序。
- 物件在最後,且依鍵的字母順序依遞增順序排列。
orderByKey
使用 orderByKey()
排序資料時,系統會依鍵值以遞增順序傳回資料。
- 可解析為 32 位元整數的鍵的子項會排在最前面,並以遞增順序排序。
- 接著是使用字串值做為鍵的子項,以字典排序方式遞增排序。
orderByValue
使用 orderByValue()
時,子項會依值排序。排序條件與 orderByChild()
相同,但會使用節點的值而非指定子項鍵的值。
卸離監聽器
您可以呼叫 Firebase 資料庫參考資料的 off()
方法,移除回呼。
您可以將單一事件監聽器做為參數傳遞至 off()
,藉此移除該事件監聽器。在位置上呼叫 off()
時不帶任何引數,會移除該位置的所有事件監聽器。
在父項事件監聽器上呼叫 off()
不會自動移除在子項節點上註冊的事件監聽器;您必須在任何子項事件監聽器上呼叫 off()
,才能移除回呼。