開始使用
如果尚未設定應用程式和資料庫存取權,請先參閱Get Started
指南。
取得 DatabaseReference
如要將資料寫入資料庫,您需要 DatabaseReference
的執行個體:
// Get the root reference location of the database. firebase::database::DatabaseReference dbref = database->GetReference();
儲存資料
將資料寫入 Firebase Realtime Database 的方法有四種:
方法 | 常見的使用方式 |
---|---|
SetValue() |
在定義的路徑 (例如 users/<user-id>/<username> ) 寫入或取代資料。 |
PushChild() |
新增至資料清單。每次呼叫 Push() 時,Firebase 都會產生專屬鍵,這個鍵也可以做為專屬 ID,例如 user-scores/<user-id>/<unique-score-id> 。 |
UpdateChildren() |
更新已定義路徑的部分鍵,不必取代所有資料。 |
RunTransaction() |
更新可能因並行更新而損毀的複雜資料。 |
在參照位置寫入、更新或刪除資料
基本寫入作業
對於基本寫入作業,您可以使用 SetValue()
將資料儲存至指定參照,並取代該路徑中的所有現有資料。您可以使用這個方法,透過支援下列項目的 Variant 型別傳遞 JSON 接受的型別:
- Null (這會刪除資料)
- 整數 (64 位元)
- 雙精度浮點數
- 布林值
- 字串
- 變數向量
- 字串對應至變數的地圖
以這種方式使用 SetValue()
會覆寫指定位置的資料,包括所有子節點。不過,您還是可以更新子項,不必重新編寫整個物件。如要允許使用者更新個人資料,可以按照下列方式更新使用者名稱:
dbref.Child("users").Child(userId).Child("username").SetValue(name);
附加至資料清單
在多使用者應用程式中,使用 PushChild()
方法將資料附加至清單。每當新子項新增至指定的 Firebase 參照時,PushChild()
方法就會產生專屬鍵。為清單中的每個新元素使用這些自動產生的鍵,多個用戶端就能同時在相同位置新增子項,不會發生寫入衝突。PushChild()
產生的專屬鍵會以時間戳記為依據,因此清單項目會自動依時間順序排列。
您可以使用 PushChild()
方法傳回的新資料參照,取得子項目的自動產生鍵值,或為子項目設定資料。對 PushChild()
參照呼叫 GetKey()
會傳回自動產生的鍵值。
更新特定欄位
如要同時寫入節點的特定子項,而不覆寫其他子節點,請使用 UpdateChildren()
方法。
呼叫 UpdateChildren()
時,您可以指定鍵的路徑,更新較低層級的子項值。如果資料儲存在多個位置,以便更妥善地擴充,您可以使用資料扇出更新所有資料執行個體。舉例來說,遊戲可能會有類似這樣的 LeaderboardEntry
類別:
class LeaderboardEntry { std::string uid; int score = 0; public: LeaderboardEntry() { } LeaderboardEntry(std::string uid, int score) { this->uid = uid; this->score = score; } std::map<std::string, Object> ToMap() { std::map<string, Variant> result = new std::map<string, Variant>(); result["uid"] = Variant(uid); result["score"] = Variant(score); return result; } }
如要建立 LeaderboardEntry
,並同時更新至最近得分動態消息和使用者自己的得分清單,遊戲會使用下列程式碼:
void WriteNewScore(std::string userId, int score) { // Create new entry at /user-scores/$userid/$scoreid and at // /leaderboard/$scoreid simultaneously std::string key = dbref.Child("scores").PushChild().GetKey(); LeaderBoardEntry entry = new LeaderBoardEntry(userId, score); std::map<std::string, Variant> entryValues = entry.ToMap(); std::map<string, Variant> childUpdates = new std::map<string, Variant>(); childUpdates["/scores/" + key] = entryValues; childUpdates["/user-scores/" + userId + "/" + key] = entryValues; dbref.UpdateChildren(childUpdates); }
這個範例會使用 PushChild()
在節點中建立項目,其中包含 /scores/$key
中所有使用者的項目,並同時使用 key()
擷取金鑰。然後,您可以使用該鍵在 /user-scores/$userid/$key
中建立使用者的第二個分數項目。
使用這些路徑,您只需呼叫一次 UpdateChildren()
,即可同時更新 JSON 樹狀結構中的多個位置,例如這個範例會在兩個位置建立新項目。以這種方式進行的同步更新具有不可分割的特性:所有更新都會成功,或所有更新都會失敗。
刪除資料
如要刪除資料,最簡單的方法是在該資料位置的參照上呼叫 RemoveValue()
。
您也可以指定 null
Variant
做為其他寫入作業 (例如 SetValue()
或 UpdateChildren()
) 的值,藉此刪除資料。您可以使用這項技術搭配 UpdateChildren()
,在單次 API 呼叫中刪除多個子項。
瞭解資料的提交時間。
如要瞭解資料何時會提交至 Firebase Realtime Database 伺服器,請檢查 Future 結果是否成功。
將資料儲存為交易
處理可能因並行修改而損毀的資料 (例如遞增計數器) 時,可以使用交易作業。您會為這項作業提供 DoTransaction
函式。這項更新函式會將資料的目前狀態做為引數,並傳回您想寫入的新所需狀態。如果其他用戶端在您的新值成功寫入位置之前寫入該位置,系統會使用新的目前值再次呼叫更新函式,並重試寫入作業。
舉例來說,您可以在遊戲中允許使用者更新排行榜,顯示前五名最高分:
void AddScoreToLeaders(std::string email, long score, DatabaseReference leaderBoardRef) { leaderBoardRef.RunTransaction([](firebase::database::MutableData* mutableData) { if (mutableData.children_count() >= MaxScores) { long minScore = LONG_MAX; MutableData *minVal = null; std::vector<MutableData> children = mutableData.children(); std::vector<MutableData>::iterator it; for (it = children.begin(); it != children.end(); ++it) { if (!it->value().is_map()) continue; long childScore = (long)it->Child("score").value().int64_value(); if (childScore < minScore) { minScore = childScore; minVal = &*it; } } if (minScore > score) { // The new score is lower than the existing 5 scores, abort. return kTransactionResultAbort; } // Remove the lowest score. children.Remove(minVal); } // Add the new high score. std::map<std::string, Variant> newScoreMap = new std::map<std::string, Variant>(); newScoreMap["score"] = score; newScoreMap["email"] = email; children.Add(newScoreMap); mutableData->set_value(children); return kTransactionResultSuccess; }); }
如果多位使用者同時記錄分數,或用戶端有過時的資料,使用交易可避免排行榜資料不正確。如果交易遭拒,伺服器會將目前值傳回給用戶端,後者會使用更新後的值再次執行交易。這個程序會重複執行,直到交易獲得接受或嘗試次數過多為止。
離線寫入資料
如果用戶端失去網路連線,應用程式仍會正常運作。
連線至 Firebase 資料庫的每個用戶端都會維護任何有效資料的內部版本。寫入資料時,系統會先寫入這個本機版本。Firebase 用戶端隨後會盡力將資料與遠端資料庫伺服器和其他用戶端同步。
因此,所有寫入資料庫的作業都會立即觸發本機事件,然後才將資料寫入伺服器。也就是說,無論網路延遲或連線狀況如何,應用程式都能保持回應。
重新建立連線後,應用程式會收到適當的事件集,讓用戶端與目前的伺服器狀態同步,不必撰寫任何自訂程式碼。