Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

Enregistrement de données avec Firebase Realtime Database pour C++

Commencer

Voir la Get Started premier guide si vous ne l' avez pas encore configuré votre application et l' accès à la base de données.

Obtenir une référence de base de données

Pour les données d'écriture à la base de données, vous avez besoin d' une instance de DatabaseReference :

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

La sauvegarde des données

Il existe quatre méthodes pour écrire des données dans la base de données en temps réel Firebase :

Méthode Utilisations courantes
SetValue() Ecrire ou remplacer les données à un chemin défini, comme les users/<user-id>/<username> d' users/<user-id>/<username> .
PushChild() Ajouter à une liste de données. Chaque fois que vous appelez Push() , Firebase génère une clé unique qui peut également être utilisé comme identifiant unique, tel que l' user-scores/<user-id>/<unique-score-id> .
UpdateChildren() Mettez à jour certaines des clés pour un chemin défini sans remplacer toutes les données.
RunTransaction() Mettez à jour les données complexes qui pourraient être corrompues par des mises à jour simultanées.

Écrire, mettre à jour ou supprimer des données à une référence

Opérations d'écriture de base

Pour les opérations d'écriture de base, vous pouvez utiliser SetValue() pour enregistrer les données à une référence spécifiée, de remplacer toutes les données existantes sur ce chemin. Vous pouvez utiliser cette méthode pour transmettre les types acceptés par JSON via un type Variant qui prend en charge :

  • Null (cela supprime les données)
  • Entiers (64 bits)
  • Nombres à virgule flottante double précision
  • Booléens
  • Cordes
  • Vecteurs de variantes
  • Mappages des chaînes aux variantes

L' utilisation SetValue() de cette manière écrasera les données à l'emplacement spécifié, y compris les nœuds enfants. Cependant, vous pouvez toujours mettre à jour un enfant sans réécrire l'intégralité de l'objet. Si vous souhaitez autoriser les utilisateurs à mettre à jour leurs profils, vous pouvez mettre à jour le nom d'utilisateur comme suit :

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

Ajouter à une liste de données

Utilisez la PushChild() méthode pour ajouter des données à une liste dans les applications multi - utilisateur. Le PushChild() méthode génère une clé unique à chaque fois qu'un nouvel enfant est ajouté à la référence Firebase spécifiée. En utilisant ces clés générées automatiquement pour chaque nouvel élément de la liste, plusieurs clients peuvent ajouter des enfants au même emplacement en même temps sans conflits d'écriture. La clé unique générée par PushChild() est basée sur un horodatage, de sorte que les éléments de la liste sont automatiquement classés par ordre chronologique.

Vous pouvez utiliser la référence aux nouvelles données renvoyées par le PushChild() méthode pour obtenir la valeur de la clé de l' enfant ou généré automatiquement les données du jeu pour l'enfant. Appel GetKey() sur un PushChild() référence renvoie la valeur de la clé générée automatiquement.

Mettre à jour des champs spécifiques

Pour écrire simultanément aux enfants spécifiques d'un noeud sans écraser les autres nœuds enfants, utilisez la UpdateChildren() méthode.

Lors de l' appel UpdateChildren() , vous pouvez mettre à jour les valeurs des enfants de niveau inférieur en spécifiant un chemin pour la clé. Si les données sont stockées dans plusieurs endroits à l' échelle mieux, vous pouvez mettre à jour toutes les instances de ces données à l' aide de données sortance . Par exemple, un jeu peut avoir une LeaderboardEntry classe comme ceci:

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

Pour créer un LeaderboardEntry et mettre à jour simultanément à l'alimentation récente partition et propre liste de points de l'utilisateur, le jeu utilise le code suivant:

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

Cet exemple utilise PushChild() pour créer une entrée dans le nœud contenant des entrées pour tous les utilisateurs à /scores/$key et récupérer simultanément sur la touche avec la key() . La clé peut être utilisée pour créer une deuxième entrée dans les scores à l'utilisateur /user-scores/$userid/$key .

L' utilisation de ces chemins, vous pouvez effectuer des mises à jour simultanées à plusieurs endroits dans l'arborescence JSON avec un seul appel à UpdateChildren() , comme la façon dont cet exemple crée la nouvelle entrée dans les deux endroits. Les mises à jour simultanées effectuées de cette manière sont atomiques : soit toutes les mises à jour réussissent, soit toutes les mises à jour échouent.

Suprimmer les données

La façon la plus simple de suppression de données est d'appeler RemoveValue() sur une référence à l'emplacement de ces données.

Vous pouvez également supprimer en spécifiant un null Variant comme la valeur pour une autre opération d'écriture tels que SetValue() ou UpdateChildren() . Vous pouvez utiliser cette technique avec UpdateChildren() pour supprimer plusieurs enfants dans un seul appel API.

Sachez quand vos données sont validées.

Pour savoir quand vos données sont commis au serveur de base de données en temps réel Firebase, vérifiez le futur résultat pour le succès.

Enregistrer les données en tant que transactions

Lorsque vous travaillez avec des données qui pourraient être corrompues par des modifications simultanées telles que les compteurs supplémentaires, vous pouvez utiliser une opération de transaction . Vous donnez cette opération une DoTransaction fonction. Cette fonction de mise à jour prend l'état actuel des données comme argument et renvoie le nouvel état souhaité que vous souhaitez écrire. Si un autre client écrit à l'emplacement avant que votre nouvelle valeur ne soit écrite avec succès, votre fonction de mise à jour est à nouveau appelée avec la nouvelle valeur actuelle et l'écriture est retentée.

Par exemple, dans un jeu, vous pouvez autoriser les utilisateurs à mettre à jour un classement avec les cinq meilleurs scores :

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

L'utilisation d'une transaction empêche le classement d'être incorrect si plusieurs utilisateurs enregistrent des scores en même temps ou si le client avait des données périmées. Si la transaction est rejetée, le serveur renvoie la valeur actuelle au client, qui exécute à nouveau la transaction avec la valeur mise à jour. Cela se répète jusqu'à ce que la transaction soit acceptée ou que trop de tentatives aient été effectuées.

Écrire des données hors ligne

Si un client perd sa connexion réseau, votre application continuera à fonctionner correctement.

Chaque client connecté à une base de données Firebase conserve sa propre version interne de toutes les données actives. Lorsque les données sont écrites, elles sont d'abord écrites dans cette version locale. Le client Firebase synchronise ensuite ces données avec les serveurs de base de données distants et avec d'autres clients au mieux.

Par conséquent, toutes les écritures dans la base de données déclenchent des événements locaux immédiatement, avant que des données ne soient écrites sur le serveur. Cela signifie que votre application reste réactive quelle que soit la latence ou la connectivité du réseau.

Une fois la connectivité rétablie, votre application reçoit l'ensemble d'événements approprié afin que le client se synchronise avec l'état actuel du serveur, sans avoir à écrire de code personnalisé.

Prochaines étapes