透過 C++ 適用的 Firebase 即時資料庫節省資料

開始使用

如果您尚未參閱 Get Started 指南,請先參閱 先設定應用程式並存取資料庫。

取得 DatabaseReference

如要將資料寫入資料庫,您需要 DatabaseReference 的執行個體:

    // Get the root reference location of the database.
    firebase::database::DatabaseReference dbref = database->GetReference();

正在儲存資料

將資料寫入 Firebase 即時資料庫的方法有四種:

方法 常見的使用方式
SetValue() 將資料寫入或取代到已定義的路徑,例如 users/<user-id>/<username>
PushChild() 新增至資料清單。每次你撥打電話 Push(),Firebase 會產生一組專屬金鑰,也可使用這些金鑰 是專屬 ID user-scores/<user-id>/<unique-score-id>
UpdateChildren() 更新已定義路徑的部分鍵,但不要替換所有 實體媒介包括儲存空間陣列 傳統硬碟、磁帶和 USB 隨身碟等
RunTransaction() 更新可能因為並行更新而損毀的複雜資料。

寫入、更新或刪除參照中的資料

基本寫入作業

如果是基本寫入作業,您可以使用 SetValue() 將資料儲存至 來取代該路徑中的任何現有資料。您可以使用 方法透過支援的 Variant 類型傳遞 JSON 接受的類型:

  • 空值 (這會刪除資料)
  • 整數 (64 位元)
  • 雙精度浮點數
  • 布林值
  • 字串
  • 變體向量
  • 將字串對應至 Variants

以這種方式使用 SetValue() 會覆寫指定位置的資料, 包括任何子節點不過,您仍可在沒有權限的情況下更新孩子 重寫整個物件如要允許使用者更新個人資料 您可以按照下列方式更新使用者名稱:

dbref.Child("users").Child(userId).Child("username").SetValue(name);

附加至資料清單

使用 PushChild() 方法,將資料附加至多使用者應用程式中的清單。 PushChild() 方法會在每次新金鑰時產生專屬金鑰 子元素會加入指定的 Firebase 參考資料。只要使用這些節點 自動產生及自動生成的索引鍵,因此可以有多個用戶端 同時將子項新增到相同的位置,而不會發生寫入衝突。 PushChild() 產生的不重複索引鍵依據時間戳記,所以清單項目會 會自動依時間排序。

您可以使用 PushChild() 方法傳回新資料的參照 來取得自動產生的鍵值,或設定子項的資料。 對 PushChild() 參照呼叫 GetKey() 會傳回 自動產生的金鑰

更新特定欄位

於不覆寫其他節點的情況下,同時寫入節點的特定子項 子節點,請使用 UpdateChildren() 方法。

呼叫 UpdateChildren() 時,您可以透過 指定金鑰的路徑如果資料儲存在多個位置,以便進行擴充 您可以使用 kubectl 指令 資料擴散傳遞。舉例來說 遊戲可能有如下所示的 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 即時資料庫伺服器,請查看 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 用戶端會將這些資料與遠端資料庫同步處理 並與其他用戶端共用。

因此,所有寫入資料庫的動作都會立即觸發本機事件, 任何資料都會寫入伺服器也就是說,您的應用程式 回應,無論網路延遲或連線。

連線恢復後,應用程式會收到一組適當的 以便用戶端與目前的伺服器狀態同步, 即可撰寫任何自訂程式碼

後續步驟