取得資料庫參照
如要從資料庫讀取或寫入資料,您需要 firebase.database.Reference
的執行個體:
Web
import { getDatabase } from "firebase/database"; const database = getDatabase();
Web
var database = firebase.database();
讀取及寫入清單
附加至資料清單
使用 push()
方法,將資料附加至多使用者應用程式中的清單。每當在指定的 Firebase 參考資料中加入新子項時,push()
方法就會產生專屬金鑰。透過為清單中的每個新元素使用自動產生的金鑰,多個用戶端即可同時將子項新增至相同位置,而不會發生寫入衝突。push()
產生的唯一索引鍵會根據時間戳記,因此清單項目會自動依時間排序。
您可以參照 push()
方法傳回新資料的參照,取得子項自動產生的鍵值,或為子項設定資料。push()
參照的 .key
屬性包含自動產生的金鑰。
您可以使用這些自動產生的金鑰來簡化資料結構。詳情請參閱資料擴散傳遞範例。
舉例來說,push()
可用來將新貼文新增至社交應用程式的貼文清單:
Web
import { getDatabase, ref, push, set } from "firebase/database"; // Create a new post reference with an auto-generated id const db = getDatabase(); const postListRef = ref(db, 'posts'); const newPostRef = push(postListRef); set(newPostRef, { // ... });
Web
// Create a new post reference with an auto-generated id var postListRef = firebase.database().ref('posts'); var newPostRef = postListRef.push(); newPostRef.set({ // ... });
監聽子事件
當作業發生在節點子項發生的特定作業時 (例如透過 push()
方法新增的子項,或透過 update()
方法更新子項),就會觸發子項事件。
活動 | 一般用量 |
---|---|
child_added |
擷取項目清單,或監聽附加項目清單。 每個現有子項都會觸發此事件一次,之後每次將新子項新增至指定路徑時,就會再次觸發此事件。事件監聽器傳遞了含有新子項資料的快照。 |
child_changed |
監聽清單中項目的變更。每當修改子節點時,就會觸發這個事件。這也包括對子節點子系所做的任何修改。傳遞至事件監聽器的快照會包含子項的更新資料。 |
child_removed |
監聽已從清單中移除的項目。移除立即子項時,就會觸發這個事件。傳遞至回呼區塊的快照會包含已移除子項的資料。 |
child_moved |
監聽已排序清單中項目順序的變更。
child_moved 事件一律會遵循導致項目順序變更的 child_changed 事件 (以目前的排序方式為準)。 |
這兩者都有助於監聽資料庫中特定節點的變更。舉例來說,社交網誌應用程式可以搭配使用下列方法,監控貼文留言中的活動,如下所示:
Web
import { getDatabase, ref, onChildAdded, onChildChanged, onChildRemoved } from "firebase/database"; const db = getDatabase(); const commentsRef = ref(db, 'post-comments/' + postId); onChildAdded(commentsRef, (data) => { addCommentElement(postElement, data.key, data.val().text, data.val().author); }); onChildChanged(commentsRef, (data) => { setCommentValues(postElement, data.key, data.val().text, data.val().author); }); onChildRemoved(commentsRef, (data) => { deleteComment(postElement, data.key); });
Web
var commentsRef = firebase.database().ref('post-comments/' + postId); commentsRef.on('child_added', (data) => { addCommentElement(postElement, data.key, data.val().text, data.val().author); }); commentsRef.on('child_changed', (data) => { setCommentValues(postElement, data.key, data.val().text, data.val().author); }); commentsRef.on('child_removed', (data) => { deleteComment(postElement, data.key); });
監聽價值事件
雖然我們建議您監聽子事件來讀取資料清單,但在某些情況下,監聽清單參照中的值事件會很實用。
將 value
觀察器附加至資料清單後,整個資料清單會以單一快照的形式傳回,接著您可以循環顯示,存取個別子項。
即使查詢只有一個符合項目,快照仍是一個清單,它只會包含一個項目。如要存取該項目,您需要循環處理結果:
Web
import { getDatabase, ref, onValue } from "firebase/database"; const db = getDatabase(); const dbRef = ref(db, '/a/b/c'); onValue(dbRef, (snapshot) => { snapshot.forEach((childSnapshot) => { const childKey = childSnapshot.key; const childData = childSnapshot.val(); // ... }); }, { onlyOnce: true });
Web
ref.once('value', (snapshot) => { snapshot.forEach((childSnapshot) => { var childKey = childSnapshot.key; var childData = childSnapshot.val(); // ... }); });
如果您想在單一作業中擷取清單的所有子項,而不監聽其他子項新增事件,這種模式就能派上用場。
排序及篩選資料
您可以使用即時資料庫 Query
類別,擷取依鍵、值或子項值排序的資料。您也可以篩選排序結果,以達到特定結果數量、鍵/值範圍。
排序資料
如要擷取經過排序的資料,請先指定一種依順序排序的方法來決定結果的排序方式:
方法 | 用量 |
---|---|
orderByChild() |
按指定子項鍵或巢狀子路徑的值排序結果。 |
orderByKey()
| 按子項鍵排序結果。 |
orderByValue() |
按照子項值排序結果。 |
一次只能使用「一個」排序方法。在同一查詢中多次呼叫依順序的方法呼叫會擲回錯誤。
以下範例說明如何擷取使用者最受歡迎的貼文清單 (依星級評等排序):
Web
import { getDatabase, ref, query, orderByChild } from "firebase/database"; import { getAuth } from "firebase/auth"; const db = getDatabase(); const auth = getAuth(); const myUserId = auth.currentUser.uid; const topUserPostsRef = query(ref(db, 'user-posts/' + myUserId), orderByChild('starCount'));
Web
var myUserId = firebase.auth().currentUser.uid; var topUserPostsRef = firebase.database().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
鍵底下巢狀的值來排序清單元素。
Web
import { getDatabase, ref, query, orderByChild } from "firebase/database"; const db = getDatabase(); const mostViewedPosts = query(ref(db, 'posts'), orderByChild('metrics/views'));
Web
var mostViewedPosts = firebase.database().ref('posts').orderByChild('metrics/views');
如要進一步瞭解其他資料類型的排序方式,請參閱查詢資料的排序方式。
篩選資料
如要篩選資料,您可以在建構查詢時,將任何限製或範圍方法與排序方法結合。
方法 | 用量 |
---|---|
limitToFirst() |
設定要從已排序結果清單開頭傳回的項目數量上限。 |
limitToLast() |
設定從已排序結果清單結尾傳回的項目數量上限。 |
startAt() |
根據所選順序,傳回大於或等於指定鍵或值的項目。 |
startAfter() |
視所選方法而定,傳回大於指定鍵或值的項目。 |
endAt() |
依據所選順序,傳回小於或等於指定鍵或值的項目。 |
endBefore() |
視所選的順序而定,傳回小於指定鍵或值的項目。 |
equalTo() |
根據所選方法,傳回與指定鍵或值相等的項目。 |
有別於依序執行排序的方式,您可以合併多個限製或範圍函式。舉例來說,您可以結合 startAt()
和 endAt()
方法,將結果限制為指定範圍內的值。
限制結果數量
您可以使用 limitToFirst()
和 limitToLast()
方法,設定要針對特定事件同步處理的子項數量上限。舉例來說,如果您使用 limitToFirst()
將限制設為 100,則一開始只會收到 100 個 child_added
事件。如果您在 Firebase 資料庫中儲存的項目少於 100 個,則每個項目都會觸發 child_added
事件。
項目有變動時,對於輸入查詢的項目,您會收到 child_added
事件,而為了讓總數維持在 100,則從項目中排除為 child_removed
事件。
以下範例展示網誌應用程式如何定義查詢,以擷取所有使用者最新發布的 100 篇文章清單:
Web
import { getDatabase, ref, query, limitToLast } from "firebase/database"; const db = getDatabase(); const recentPostsRef = query(ref(db, 'posts'), limitToLast(100));
Web
var recentPostsRef = firebase.database().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()
,才能移除回呼。