使用 Web 上的數據列表

獲取數據庫參考

要從數據庫讀取或寫入數據,您需要一個firebase.database.Reference實例:

Web version 9

import { getDatabase } from "firebase/database";

const database = getDatabase();

Web version 8

var database = firebase.database();

閱讀和寫作清單

附加到數據列表

使用push()方法將數據附加到多用戶應用程序中的列表。每次將新子項添加到指定的 Firebase 引用時, push()方法都會生成一個唯一鍵。通過為列表中的每個新元素使用這些自動生成的鍵,多個客戶端可以同時將子元素添加到同一位置,而不會發生寫入衝突。 push()生成的唯一鍵基於時間戳,因此列表項會自動按時間順序排列。

您可以使用對push()方法返回的新數據的引用來獲取子項自動生成的鍵的值或為子項設置數據。 push()引用的.key屬性包含自動生成的密鑰。

您可以使用這些自動生成的鍵來簡化數據結構的扁平化。有關詳細信息,請參閱數據扇出示例

例如, push()可用於將新帖子添加到社交應用程序的帖子列表中:

Web version 9

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 version 8

// 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事件(基於您當前的 order-by 方法)。

這些中的每一個都可用於監聽數據庫中特定節點的更改。例如,社交博客應用程序可能會同時使用這些方法來監控帖子評論中的活動,如下所示:

Web version 9

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 version 8

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 version 9

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 version 8

ref.once('value', (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    var childKey = childSnapshot.key;
    var childData = childSnapshot.val();
    // ...
  });
});

當您想在單個操作中獲取列表的所有子項而不是偵聽附加的子項添加事件時,此模式很有用。

排序和過濾數據

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

排序數據

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

方法用法
orderByChild()按指定子鍵或嵌套子路徑的值對結果進行排序。
orderByKey()按子鍵排序結果。
orderByValue()按子值排序結果。

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

以下示例演示瞭如何檢索按星數排序的用戶熱門帖子列表:

Web version 9

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 version 8

var myUserId = firebase.auth().currentUser.uid;
var topUserPostsRef = firebase.database().ref('user-posts/' + myUserId).orderByChild('starCount');

這定義了一個查詢,當與子偵聽器結合使用時,該查詢根據用戶 ID 將客戶端與數據庫中路徑中的用戶帖子同步,按每個帖子收到的星數排序。這種使用 ID 作為索引鍵的技術稱為數據扇出,您可以在Structure Your Database中了解更多信息。

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 version 9

import { getDatabase, ref, query, orderByChild } from "firebase/database";

const db = getDatabase();
const mostViewedPosts = query(ref(db, 'posts'), orderByChild('metrics/views'));

Web version 8

var mostViewedPosts = firebase.database().ref('posts').orderByChild('metrics/views');

有關其他數據類型如何排序的詳細信息,請參閱查詢數據的排序方式

過濾數據

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

方法用法
limitToFirst()設置從有序結果列表的開頭返回的最大項目數。
limitToLast()設置從有序結果列表末尾返回的最大項目數。
startAt()根據選擇的 order-by 方法,返回大於或等於指定鍵或值的項目。
startAfter()根據選擇的 order-by 方法返回大於指定鍵或值的項目。
endAt()根據選擇的 order-by 方法,返回小於或等於指定鍵或值的項目。
endBefore()根據選擇的 order-by 方法返回小於指定鍵或值的項目。
equalTo()根據選擇的 order-by 方法,返回等於指定鍵或值的項目。

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

限制結果數量

您可以使用limitToFirst()limitToLast()方法來設置要為給定事件同步的最大子節點數。例如,如果您使用limitToFirst()將限制設置為 100,那麼您最初最多只能收到 100 個child_added事件。如果您的 Firebase 數據庫中存儲的項目少於 100 個,則會為每個項目觸發一個child_added事件。

隨著項目的變化,您會收到進入查詢的項目的child_added事件和退出查詢的項目的child_removed事件,因此總數保持在 100。

以下示例演示了示例博客應用程序如何定義一個查詢來檢索所有用戶最近發布的 100 個帖子的列表:

Web version 9

import { getDatabase, ref, query, limitToLast } from "firebase/database";

const db = getDatabase();
const recentPostsRef = query(ref(db, 'posts'), limitToLast(100));

Web version 8

var recentPostsRef = firebase.database().ref('posts').limitToLast(100);

這個例子只定義了一個查詢,要真正同步數據,它需要一個附加的監聽器。

按鍵或值過濾

您可以使用startAt()startAfter()endAt()endBefore()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()中的相同,除了使用節點的值而不是指定子鍵的值。

分離監聽器

通過在 Firebase 數據庫引用上調用off()方法來刪除回調。

您可以通過將單個偵聽器作為參數傳遞給off()來刪除它。在不帶參數的位置調用off()會刪除該位置的所有偵聽器。

在父監聽器上調用off()不會自動刪除在其子節點上註冊的監聽器;還必須在任何子偵聽器上調用off()以刪除回調。

下一步