本文檔介紹了檢索數據的基礎知識以及如何排序和過濾 Firebase 數據。
在你開始之前
確保您已設置您的應用程序並且可以訪問Get Started
指南中所述的數據庫。
檢索數據
通過一次性調用GetValue()
或附加到FirebaseDatabase
引用上的ValueListener
來檢索 Firebase 數據。值偵聽器為數據的初始狀態調用一次,並在數據更改時再次調用。
獲取數據庫引用
要將數據寫入數據庫,您需要一個DatabaseReference
實例:
// Get the root reference location of the database. firebase::database::DatabaseReference dbref = database->GetReference();
一次讀取數據
您可以使用GetValue()
方法一次讀取給定路徑中內容的靜態快照。任務結果將包含一個快照,其中包含該位置的所有數據,包括子數據。如果沒有數據,則返回的快照為null
。
firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("Leaders").GetValue();
此時已發出請求,但我們必須等待 Future 完成才能讀取值。由於遊戲通常在循環中運行,並且比其他應用程序更少受回調驅動,因此您通常會輪詢完成。
// In the game loop that polls for the result... if (result.status() != firebase::kFutureStatusPending) { if (result.status() != firebase::kFutureStatusComplete) { LogMessage("ERROR: GetValue() returned an invalid result."); // Handle the error... } else if (result.error() != firebase::database::kErrorNone) { LogMessage("ERROR: GetValue() returned error %d: %s", result.error(), result.error_message()); // Handle the error... } else { firebase::database::DataSnapshot snapshot = result.result(); // Do something with the snapshot... } }
這顯示了一些基本的錯誤檢查,有關錯誤檢查的更多信息以及確定結果何時準備就緒的方法,請參閱firebase::Future參考。
監聽事件
您可以添加偵聽器以訂閱數據更改:
ValueListener
基類
打回來 | 典型用法 |
---|---|
OnValueChanged | 讀取並監聽路徑全部內容的變化。 |
OnChildListener
基類
OnChildAdded | 檢索項目列表或偵聽對項目列表的添加。建議與OnChildChanged 和OnChildRemoved 一起使用以監視對列表的更改。 |
OnChildChanged | 偵聽列表中項目的更改。與OnChildAdded 和OnChildRemoved 一起使用以監視對列表的更改。 |
OnChildRemoved | 偵聽從列表中刪除的項目。與OnChildAdded 和OnChildChanged 一起使用以監視對列表的更改。 |
OnChildMoved | 監聽有序列表中項目順序的變化。由於項目的順序發生變化(基於您當前的排序方式), OnChildMoved 回調始終遵循OnChildChanged 回調。 |
值監聽類
您可以使用OnValueChanged
回調來訂閱給定路徑中內容的更改。當監聽器被附加時,這個回調被觸發一次,每次數據(包括孩子)發生變化時再次觸發。向回調傳遞一個快照,其中包含該位置的所有數據,包括子數據。如果沒有數據,則返回的快照為null
。
以下示例演示了從數據庫中檢索排行榜分數的遊戲:
class LeadersValueListener : public firebase::database::ValueListener { public: void OnValueChanged( const firebase::database::DataSnapshot& snapshot) override { // Do something with the data in snapshot... } void OnCancelled(const firebase::database::Error& error_code, const char* error_message) override { LogMessage("ERROR: LeadersValueListener canceled: %d: %s", error_code, error_message); } }; // Elsewhere in the code... LeadersValueListener* listener = new LeadersValueListener(); firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("Leaders").AddValueListener(listener);
Future<DataSnaphot>
結果包含事件發生時數據庫中指定位置的數據。在快照上調用value()
會返回表示數據的Variant
。
在本例中,還重寫了OnCancelled
方法,以查看讀取是否被取消。例如,如果客戶端沒有從 Firebase 數據庫位置讀取的權限,則可以取消讀取。 database::Error
將指出失敗的原因。
ChildListener類
觸發子事件以響應發生在節點子節點上的特定操作,這些操作來自某個操作,例如通過PushChild()
方法添加的新子節點或通過UpdateChildren()
方法更新的子節點。這些中的每一個都可以用於偵聽數據庫中特定節點的更改。例如,遊戲可能會同時使用這些方法來監控遊戲會話評論中的活動,如下所示:
class SessionCommentsChildListener : public firebase::database::ChildListener { public: void OnChildAdded(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnChildChanged(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnChildRemoved( const firebase::database::DataSnapshot& snapshot) override { // Do something with the data in snapshot ... } void OnChildMoved(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnCancelled(const firebase::database::Error& error_code, const char* error_message) override { LogMessage("ERROR: SessionCommentsChildListener canceled: %d: %s", error_code, error_message); } }; // elsewhere .... SessionCommentsChildListener* listener = new SessionCommentsChildListener(); firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("GameSessionComments").AddChildListener(listener);
OnChildAdded
回調通常用於檢索 Firebase 數據庫中的項目列表。 OnChildAdded
回調會為每個現有子項調用一次,然後在每次將新子項添加到指定路徑時再次調用。向偵聽器傳遞包含新孩子數據的快照。
每次修改子節點時都會調用OnChildChanged
回調。這包括對子節點後代的任何修改。它通常與OnChildAdded
和OnChildRemoved
調用結合使用,以響應對項目列表的更改。傳遞給偵聽器的快照包含子項的更新數據。
OnChildRemoved
回調在刪除直接子項時觸發。它通常與OnChildAdded
和OnChildChanged
回調結合使用。傳遞給回調的快照包含已刪除子項的數據。
每當OnChildMoved
調用由OnChildChanged
子項重新排序的更新引發時,就會觸發 OnChildMoved 回調。它與使用OrderByChild
或OrderByValue
排序的數據一起使用。
排序和過濾數據
您可以使用實時數據庫Query
類來檢索按鍵、值或子值排序的數據。您還可以將排序結果過濾為特定數量的結果或一定範圍的鍵或值。
排序數據
要檢索排序的數據,首先指定一種排序方法以確定結果的排序方式:
方法 | 用法 |
---|---|
OrderByChild() | 按指定子鍵的值排序結果。 | OrderByKey() | 按子鍵排序結果。 |
OrderByValue() | 按子值排序結果。 |
您一次只能使用一種排序方法。在同一查詢中多次調用 order-by 方法會引發錯誤。
以下示例演示如何訂閱按分數排序的分數排行榜。
firebase::database::Query query = dbRef.GetReference("Leaders").OrderByChild("score"); // To get the resulting DataSnapshot either use query.GetValue() and poll the // future, or use query.AddValueListener() and register to handle the // OnValueChanged callback.
這定義了一個firebase::Query
,當它與ValueListener結合使用時,將客戶端與數據庫中的排行榜同步,按每個條目的分數排序。您可以在構建您的數據庫中閱讀更多關於高效構建數據的信息。
對OrderByChild()
方法的調用指定了對結果進行排序所依據的子鍵。在這種情況下,結果按每個孩子的"score"
值排序。有關其他數據類型如何排序的更多信息,請參閱查詢數據的排序方式。
過濾數據
要過濾數據,您可以在構造查詢時將任何 limit 或 range 方法與 order-by 方法結合使用。
方法 | 用法 |
---|---|
LimitToFirst() | 設置從有序結果列表的開頭返回的最大項目數。 |
LimitToLast() | 設置從有序結果列表末尾返回的最大項目數。 |
StartAt() | 根據所選的排序方法,返回大於或等於指定鍵或值的項目。 |
EndAt() | 根據所選的排序方法,返回小於或等於指定鍵或值的項目。 |
EqualTo() | 根據所選的排序方法,返回等於指定鍵或值的項目。 |
與排序方法不同,您可以組合多個限製或範圍函數。例如,您可以組合StartAt()
和EndAt()
方法以將結果限制在指定的值範圍內。
即使查詢只有一個匹配項,快照仍然是一個列表;它只包含一個項目。
限制結果數量
您可以使用LimitToFirst()
和LimitToLast()
方法來設置要為給定回調同步的最大子級數。例如,如果您使用LimitToFirst()
將限制設置為 100,則您最初最多只能收到 100 個OnChildAdded
回調。如果您的 Firebase 數據庫中存儲的項目少於 100 個,則會為每個項目觸發OnChildAdded
回調。
隨著項目的更改,您會收到進入查詢的項目的OnChildAdded
回調和退出查詢的項目的OnChildRemoved
回調,以便總數保持在 100。
例如,下面的代碼返回排行榜的最高分:
firebase::database::Query query = dbRef.GetReference("Leaders").OrderByChild("score").LimitToLast(1); // To get the resulting DataSnapshot either use query.GetValue() and poll the // future, or use query.AddValueListener() and register to handle the // OnValueChanged callback.
按鍵或值過濾
您可以使用StartAt()
、 EndAt()
和EqualTo()
為查詢選擇任意起點、終點和等價點。這對於分頁數據或查找包含具有特定值的子項的項目很有用。
查詢數據的排序方式
本節說明如何通過Query
類中的每個排序方法對數據進行排序。
OrderByChild
使用OrderByChild()
時,包含指定子鍵的數據按如下方式排序:
- 指定子鍵的
null
值的子項排在第一位。 - 接下來是指定子鍵值為
false
的子項。如果多個孩子的值為false
,則它們按字典順序按鍵排序。 - 接下來是指定子鍵值為
true
的子項。如果多個孩子的值為true
,則它們按字典順序按鍵排序。 - 接下來是具有數值的孩子,按升序排序。如果指定子節點的多個子節點的數值相同,則按key排序。
- 字符串位於數字之後,並按字典順序升序排序。如果指定子節點的多個子節點具有相同的值,則它們按鍵按字典順序排序。
- 對象排在最後,並按鍵按字典順序升序排序。
OrderByKey
當使用OrderByKey()
對數據進行排序時,數據將按鍵按升序返回。
- 具有可以解析為 32 位整數的鍵的孩子排在第一位,按升序排序。
- 接下來是以字符串值作為鍵的子項,按字典順序升序排序。
OrderByValue
使用OrderByValue()
時,子項按其值排序。排序標準與OrderByChild()
中的相同,除了使用節點的值而不是指定子鍵的值。
下一步
,本文檔介紹了檢索數據的基礎知識以及如何排序和過濾 Firebase 數據。
在你開始之前
確保您已設置您的應用程序並且可以訪問Get Started
指南中所述的數據庫。
檢索數據
通過一次性調用GetValue()
或附加到FirebaseDatabase
引用上的ValueListener
來檢索 Firebase 數據。值偵聽器為數據的初始狀態調用一次,並在數據更改時再次調用。
獲取數據庫引用
要將數據寫入數據庫,您需要一個DatabaseReference
實例:
// Get the root reference location of the database. firebase::database::DatabaseReference dbref = database->GetReference();
一次讀取數據
您可以使用GetValue()
方法一次讀取給定路徑中內容的靜態快照。任務結果將包含一個快照,其中包含該位置的所有數據,包括子數據。如果沒有數據,則返回的快照為null
。
firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("Leaders").GetValue();
此時已發出請求,但我們必須等待 Future 完成才能讀取值。由於遊戲通常在循環中運行,並且比其他應用程序更少受回調驅動,因此您通常會輪詢完成。
// In the game loop that polls for the result... if (result.status() != firebase::kFutureStatusPending) { if (result.status() != firebase::kFutureStatusComplete) { LogMessage("ERROR: GetValue() returned an invalid result."); // Handle the error... } else if (result.error() != firebase::database::kErrorNone) { LogMessage("ERROR: GetValue() returned error %d: %s", result.error(), result.error_message()); // Handle the error... } else { firebase::database::DataSnapshot snapshot = result.result(); // Do something with the snapshot... } }
這顯示了一些基本的錯誤檢查,有關錯誤檢查的更多信息以及確定結果何時準備就緒的方法,請參閱firebase::Future參考。
監聽事件
您可以添加偵聽器以訂閱數據更改:
ValueListener
基類
打回來 | 典型用法 |
---|---|
OnValueChanged | 讀取並監聽路徑全部內容的變化。 |
OnChildListener
基類
OnChildAdded | 檢索項目列表或偵聽對項目列表的添加。建議與OnChildChanged 和OnChildRemoved 一起使用以監視對列表的更改。 |
OnChildChanged | 偵聽列表中項目的更改。與OnChildAdded 和OnChildRemoved 一起使用以監視對列表的更改。 |
OnChildRemoved | 偵聽從列表中刪除的項目。與OnChildAdded 和OnChildChanged 一起使用以監視對列表的更改。 |
OnChildMoved | 監聽有序列表中項目順序的變化。由於項目的順序發生變化(基於您當前的排序方式), OnChildMoved 回調始終遵循OnChildChanged 回調。 |
值監聽類
您可以使用OnValueChanged
回調來訂閱給定路徑中內容的更改。當監聽器被附加時,這個回調被觸發一次,每次數據(包括孩子)發生變化時再次觸發。向回調傳遞一個快照,其中包含該位置的所有數據,包括子數據。如果沒有數據,則返回的快照為null
。
以下示例演示了從數據庫中檢索排行榜分數的遊戲:
class LeadersValueListener : public firebase::database::ValueListener { public: void OnValueChanged( const firebase::database::DataSnapshot& snapshot) override { // Do something with the data in snapshot... } void OnCancelled(const firebase::database::Error& error_code, const char* error_message) override { LogMessage("ERROR: LeadersValueListener canceled: %d: %s", error_code, error_message); } }; // Elsewhere in the code... LeadersValueListener* listener = new LeadersValueListener(); firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("Leaders").AddValueListener(listener);
Future<DataSnaphot>
結果包含事件發生時數據庫中指定位置的數據。在快照上調用value()
會返回表示數據的Variant
。
在本例中,還重寫了OnCancelled
方法,以查看讀取是否被取消。例如,如果客戶端沒有從 Firebase 數據庫位置讀取的權限,則可以取消讀取。 database::Error
將指出失敗的原因。
ChildListener類
觸發子事件以響應發生在節點子節點上的特定操作,這些操作來自某個操作,例如通過PushChild()
方法添加的新子節點或通過UpdateChildren()
方法更新的子節點。這些中的每一個都可以用於偵聽數據庫中特定節點的更改。例如,遊戲可能會同時使用這些方法來監控遊戲會話評論中的活動,如下所示:
class SessionCommentsChildListener : public firebase::database::ChildListener { public: void OnChildAdded(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnChildChanged(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnChildRemoved( const firebase::database::DataSnapshot& snapshot) override { // Do something with the data in snapshot ... } void OnChildMoved(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnCancelled(const firebase::database::Error& error_code, const char* error_message) override { LogMessage("ERROR: SessionCommentsChildListener canceled: %d: %s", error_code, error_message); } }; // elsewhere .... SessionCommentsChildListener* listener = new SessionCommentsChildListener(); firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("GameSessionComments").AddChildListener(listener);
OnChildAdded
回調通常用於檢索 Firebase 數據庫中的項目列表。 OnChildAdded
回調會為每個現有子項調用一次,然後在每次將新子項添加到指定路徑時再次調用。向偵聽器傳遞包含新孩子數據的快照。
每次修改子節點時都會調用OnChildChanged
回調。這包括對子節點後代的任何修改。它通常與OnChildAdded
和OnChildRemoved
調用結合使用,以響應對項目列表的更改。傳遞給偵聽器的快照包含子項的更新數據。
OnChildRemoved
回調在刪除直接子項時觸發。它通常與OnChildAdded
和OnChildChanged
回調結合使用。傳遞給回調的快照包含已刪除子項的數據。
每當OnChildMoved
調用由OnChildChanged
子項重新排序的更新引發時,就會觸發 OnChildMoved 回調。它與使用OrderByChild
或OrderByValue
排序的數據一起使用。
排序和過濾數據
您可以使用實時數據庫Query
類來檢索按鍵、值或子值排序的數據。您還可以將排序結果過濾為特定數量的結果或一定範圍的鍵或值。
排序數據
要檢索排序的數據,首先指定一種排序方法以確定結果的排序方式:
方法 | 用法 |
---|---|
OrderByChild() | 按指定子鍵的值排序結果。 | OrderByKey() | 按子鍵排序結果。 |
OrderByValue() | 按子值排序結果。 |
您一次只能使用一種排序方法。在同一查詢中多次調用 order-by 方法會引發錯誤。
以下示例演示如何訂閱按分數排序的分數排行榜。
firebase::database::Query query = dbRef.GetReference("Leaders").OrderByChild("score"); // To get the resulting DataSnapshot either use query.GetValue() and poll the // future, or use query.AddValueListener() and register to handle the // OnValueChanged callback.
這定義了一個firebase::Query
,當它與ValueListener結合使用時,將客戶端與數據庫中的排行榜同步,按每個條目的分數排序。您可以在構建您的數據庫中閱讀更多關於高效構建數據的信息。
對OrderByChild()
方法的調用指定了對結果進行排序所依據的子鍵。在這種情況下,結果按每個孩子的"score"
值排序。有關其他數據類型如何排序的更多信息,請參閱查詢數據的排序方式。
過濾數據
要過濾數據,您可以在構造查詢時將任何 limit 或 range 方法與 order-by 方法結合使用。
方法 | 用法 |
---|---|
LimitToFirst() | 設置從有序結果列表的開頭返回的最大項目數。 |
LimitToLast() | 設置從有序結果列表末尾返回的最大項目數。 |
StartAt() | 根據所選的排序方法,返回大於或等於指定鍵或值的項目。 |
EndAt() | 根據所選的排序方法,返回小於或等於指定鍵或值的項目。 |
EqualTo() | 根據所選的排序方法,返回等於指定鍵或值的項目。 |
與排序方法不同,您可以組合多個限製或範圍函數。例如,您可以組合StartAt()
和EndAt()
方法以將結果限制在指定的值範圍內。
即使查詢只有一個匹配項,快照仍然是一個列表;它只包含一個項目。
限制結果數量
您可以使用LimitToFirst()
和LimitToLast()
方法來設置要為給定回調同步的最大子級數。例如,如果您使用LimitToFirst()
將限制設置為 100,則您最初最多只能收到 100 個OnChildAdded
回調。如果您的 Firebase 數據庫中存儲的項目少於 100 個,則會為每個項目觸發OnChildAdded
回調。
隨著項目的更改,您會收到進入查詢的項目的OnChildAdded
回調和退出查詢的項目的OnChildRemoved
回調,以便總數保持在 100。
例如,下面的代碼返回排行榜的最高分:
firebase::database::Query query = dbRef.GetReference("Leaders").OrderByChild("score").LimitToLast(1); // To get the resulting DataSnapshot either use query.GetValue() and poll the // future, or use query.AddValueListener() and register to handle the // OnValueChanged callback.
按鍵或值過濾
您可以使用StartAt()
、 EndAt()
和EqualTo()
為查詢選擇任意起點、終點和等價點。這對於分頁數據或查找包含具有特定值的子項的項目很有用。
查詢數據的排序方式
本節說明如何通過Query
類中的每個排序方法對數據進行排序。
OrderByChild
使用OrderByChild()
時,包含指定子鍵的數據按如下方式排序:
- 指定子鍵的
null
值的子項排在第一位。 - 接下來是指定子鍵值為
false
的子項。如果多個孩子的值為false
,則它們按字典順序按鍵排序。 - 接下來是指定子鍵值為
true
的子項。如果多個孩子的值為true
,則它們按字典順序按鍵排序。 - 接下來是具有數值的孩子,按升序排序。如果指定子節點的多個子節點的數值相同,則按key排序。
- 字符串位於數字之後,並按字典順序升序排序。如果指定子節點的多個子節點具有相同的值,則它們按鍵按字典順序排序。
- 對象排在最後,並按鍵按字典順序升序排序。
OrderByKey
當使用OrderByKey()
對數據進行排序時,數據將按鍵按升序返回。
- 具有可以解析為 32 位整數的鍵的孩子排在第一位,按升序排序。
- 接下來是以字符串值作為鍵的子項,按字典順序升序排序。
OrderByValue
使用OrderByValue()
時,子項按其值排序。排序標準與OrderByChild()
中的相同,除了使用節點的值而不是指定子鍵的值。