Save the date - Google I/O returns May 18-20. Register to get the most out of the digital experience: Build your schedule, reserve space, participate in Q&As, earn Google Developer profile badges, and more. Register now
Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

Speichern von Daten mit der Firebase Realtime Database für C ++

Loslegen

Lesen Get Started zuerst die Anleitung Erste Get Started , wenn Sie Ihre App noch nicht eingerichtet haben und auf die Datenbank zugreifen.

Holen Sie sich eine DatabaseReference

Um Daten in die Datenbank zu schreiben, benötigen Sie eine Instanz von DatabaseReference :

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

Daten speichern

Es gibt vier Methoden zum Schreiben von Daten in die Firebase-Echtzeitdatenbank:

Methode Allgemeine Verwendungen
SetValue() Schreiben oder ersetzen Sie Daten in einen definierten Pfad, z. B. users/<user-id>/<username> .
PushChild() Zu einer Datenliste hinzufügen. Jedes Mal, wenn Sie Push() aufrufen, generiert Firebase einen eindeutigen Schlüssel, der auch als eindeutige Kennung verwendet werden kann, z. B. user-scores/<user-id>/<unique-score-id> .
UpdateChildren() Aktualisieren Sie einige der Schlüssel für einen definierten Pfad, ohne alle Daten zu ersetzen.
RunTransaction() Aktualisieren Sie komplexe Daten, die durch gleichzeitige Aktualisierungen beschädigt werden könnten.

Schreiben, aktualisieren oder löschen Sie Daten an einer Referenz

Grundlegende Schreibvorgänge

Für grundlegende Schreibvorgänge können Sie SetValue() , um Daten in einer angegebenen Referenz zu speichern und vorhandene Daten in diesem Pfad zu ersetzen. Mit dieser Methode können Sie von JSON akzeptierte Typen über einen Variantentyp übergeben, der Folgendes unterstützt:

  • Null (dies löscht die Daten)
  • Ganzzahlen (64-Bit)
  • Gleitkommazahlen mit doppelter Genauigkeit
  • Boolesche Werte
  • Saiten
  • Vektoren von Varianten
  • Zuordnungen von Zeichenfolgen zu Varianten

Wenn Sie SetValue() auf diese Weise verwenden, werden Daten am angegebenen Speicherort überschrieben, einschließlich aller SetValue() Knoten. Sie können jedoch weiterhin ein untergeordnetes Element aktualisieren, ohne das gesamte Objekt neu zu schreiben. Wenn Sie Benutzern erlauben möchten, ihre Profile zu aktualisieren, können Sie den Benutzernamen wie folgt aktualisieren:

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

An eine Datenliste anhängen

Verwenden Sie die PushChild() -Methode, um Daten an eine Liste in Mehrbenutzeranwendungen anzuhängen. Die PushChild() -Methode generiert jedes Mal einen eindeutigen Schlüssel, wenn der angegebenen Firebase-Referenz ein neues PushChild() hinzugefügt wird. Durch die Verwendung dieser automatisch generierten Schlüssel für jedes neue Element in der Liste können mehrere Clients gleichzeitig untergeordnete Elemente ohne Schreibkonflikte zum selben Speicherort hinzufügen. Der von PushChild() generierte eindeutige Schlüssel basiert auf einem Zeitstempel, sodass Listenelemente automatisch chronologisch sortiert werden.

Sie können den Verweis auf die neuen Daten verwenden, die von der PushChild() -Methode zurückgegeben werden, um den Wert des automatisch generierten Schlüssels des Kindes PushChild() oder Daten für das Kind PushChild() . GetKey() Sie GetKey() für eine PushChild() der Wert des automatisch generierten Schlüssels zurückgegeben.

Aktualisieren Sie bestimmte Felder

Verwenden Sie die UpdateChildren() -Methode, um gleichzeitig auf bestimmte UpdateChildren() Knoten eines Knotens zu schreiben, ohne andere UpdateChildren() Knoten zu überschreiben.

Wenn Sie UpdateChildren() aufrufen, können Sie untergeordnete Werte auf niedrigerer Ebene aktualisieren, indem Sie einen Pfad für den Schlüssel UpdateChildren() . Wenn Daten an mehreren Orten gespeichert werden, um eine bessere Skalierung zu erreichen, können Sie alle Instanzen dieser Daten mithilfe des Daten-Fan-Outs aktualisieren. Ein Spiel könnte beispielsweise eine LeaderboardEntry Klasse wie die folgende haben:

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;
  }
}

Um einen LeaderboardEntry zu erstellen und ihn gleichzeitig auf den aktuellen Score-Feed und die eigene Score-Liste des Benutzers zu aktualisieren, verwendet das Spiel den folgenden Code:

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);
}

In diesem Beispiel wird PushChild() , um einen Eintrag im Knoten zu erstellen, der Einträge für alle Benutzer unter /scores/$key und gleichzeitig den Schlüssel mit key() abzurufen. Der Schlüssel kann dann verwendet werden, um einen zweiten Eintrag in den Punktzahlen des Benutzers unter /user-scores/$userid/$key zu erstellen.

Mithilfe dieser Pfade können Sie mit einem einzigen Aufruf von UpdateChildren() gleichzeitig Aktualisierungen an mehreren Speicherorten in der JSON- UpdateChildren() , z. B. wie in diesem Beispiel der neue Eintrag an beiden Speicherorten erstellt wird. Auf diese Weise vorgenommene gleichzeitige Aktualisierungen sind atomar: Entweder sind alle Aktualisierungen erfolgreich oder alle Aktualisierungen schlagen fehl.

Daten löschen

Der einfachste Weg, Daten zu löschen, besteht darin, RemoveValue() für einen Verweis auf den Speicherort dieser Daten RemoveValue() .

Sie können auch durch Angabe eines löschen null Variant als Wert für eine weitere Schreiboperation wie SetValue() oder UpdateChildren() . Sie können diese Technik mit UpdateChildren() , um mehrere UpdateChildren() in einem einzigen API-Aufruf zu löschen.

Erfahren Sie, wann Ihre Daten festgeschrieben sind.

Überprüfen Sie das zukünftige Ergebnis auf Erfolg, um festzustellen, wann Ihre Daten auf dem Firebase Realtime Database-Server festgeschrieben werden.

Daten als Transaktionen speichern

Wenn Sie mit Daten arbeiten, die durch gleichzeitige Änderungen beschädigt werden könnten, z. B. inkrementelle Zähler, können Sie eine Transaktionsoperation verwenden . Sie geben dieser Operation eine DoTransaction Funktion. Diese Aktualisierungsfunktion verwendet den aktuellen Status der Daten als Argument und gibt den neuen gewünschten Status zurück, den Sie schreiben möchten. Wenn ein anderer Client an den Speicherort schreibt, bevor Ihr neuer Wert erfolgreich geschrieben wurde, wird Ihre Aktualisierungsfunktion mit dem neuen aktuellen Wert erneut aufgerufen und der Schreibvorgang wird wiederholt.

In einem Spiel können Sie beispielsweise Benutzern erlauben, eine Rangliste mit den fünf höchsten Punktzahlen zu aktualisieren:

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;
  });
}

Durch die Verwendung einer Transaktion wird verhindert, dass die Bestenliste falsch ist, wenn mehrere Benutzer gleichzeitig Ergebnisse aufzeichnen oder der Client veraltete Daten hat. Wenn die Transaktion abgelehnt wird, gibt der Server den aktuellen Wert an den Client zurück, der die Transaktion erneut mit dem aktualisierten Wert ausführt. Dies wird wiederholt, bis die Transaktion akzeptiert wurde oder zu viele Versuche unternommen wurden.

Daten offline schreiben

Wenn ein Client seine Netzwerkverbindung verliert, funktioniert Ihre App weiterhin ordnungsgemäß.

Jeder mit einer Firebase-Datenbank verbundene Client verwaltet seine eigene interne Version aller aktiven Daten. Wenn Daten geschrieben werden, werden sie zuerst in diese lokale Version geschrieben. Der Firebase-Client synchronisiert diese Daten dann mit den Remote-Datenbankservern und mit anderen Clients auf "Best-Effort" -Basis.

Infolgedessen lösen alle Schreibvorgänge in die Datenbank sofort lokale Ereignisse aus, bevor Daten auf den Server geschrieben werden. Dies bedeutet, dass Ihre App unabhängig von Netzwerklatenz oder Konnektivität reagiert.

Sobald die Konnektivität wiederhergestellt ist, empfängt Ihre App die entsprechenden Ereignisse, sodass der Client mit dem aktuellen Serverstatus synchronisiert wird, ohne dass benutzerdefinierter Code geschrieben werden muss.

Nächste Schritte