Zapisywanie danych w Bazie danych czasu rzeczywistego Firebase dla C++

Rozpocznij

Jeśli jeszcze nie znasz przewodnika Get Started, najpierw zapoznaj się z nim. skonfigurować aplikację i uzyskać dostęp do bazy danych.

Pobieranie odniesienia do bazy danych

Aby zapisać dane w bazie danych, potrzebujesz instancji DatabaseReference:

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

Zapisywanie danych

Są 4 metody zapisywania danych w Bazie danych czasu rzeczywistego Firebase:

Metoda Typowe zastosowania
SetValue() Zapisz lub zastąp dane w określonej ścieżce, takiej jak users/<user-id>/<username>
PushChild() Dodaj do listy danych. Za każdym razem, gdy do Ciebie dzwonisz Push(), Firebase generuje unikalny klucz, którego można użyć również jako unikalny identyfikator, np. user-scores/<user-id>/<unique-score-id>
UpdateChildren() Zaktualizuj niektóre klucze zdefiniowanej ścieżki bez zastępowania wszystkich dane.
RunTransaction() Aktualizuj złożone dane, które mogą zostać uszkodzone w wyniku równoczesnych aktualizacji.

Zapisywanie, aktualizowanie i usuwanie danych w odwołaniach

Podstawowe operacje zapisu

W przypadku podstawowych operacji zapisu możesz użyć funkcji SetValue(), aby zapisać dane w określone odwołanie, zastępując wszystkie istniejące dane w tej ścieżce. Możesz użyć tej do przekazywania typów akceptowanych przez plik JSON za pomocą typu wariantu, który obsługuje:

  • Null (spowoduje to usunięcie danych)
  • Liczba całkowita (64-bitowa)
  • Liczba zmiennoprzecinkowa z podwójną precyzją
  • Wartość logiczna
  • Ciągi znaków
  • Wektory wariantów
  • Mapy ciągów znaków na warianty

Użycie tego parametru SetValue() spowoduje zastąpienie danych w określonej lokalizacji, łącznie z węzłami podrzędnymi. Nadal możesz jednak zaktualizować dziecko bez cały obiekt jest tworzony na nowo. Jeśli chcesz zezwolić użytkownikom na aktualizowanie swoich profili możesz zmienić nazwę użytkownika w następujący sposób:

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

Dołącz do listy danych

Użyj metody PushChild(), aby dołączać dane do listy w aplikacjach, które mają wielu użytkowników. Metoda PushChild() generuje unikalny klucz przy każdym nowym kluczu element podrzędny został dodany do określonego odwołania Firebase. Za pomocą tych generowanych automatycznie kluczy dla każdego nowego elementu na liście, kilka klientów może dodawanie dzieci w tym samym czasie do tej samej lokalizacji bez konfliktów zapisu. unikalny klucz generowany przez usługę PushChild() jest oparty na sygnaturze czasowej, więc elementy listy są automatycznie uporządkowane chronologicznie.

Możesz użyć odwołania do nowych danych zwróconych przez metodę PushChild() , aby pobrać wartość automatycznie wygenerowanego klucza wydawcy podrzędnego lub ustawić dane dla niego. Wywołanie GetKey() w przypadku odwołania do PushChild() zwraca wartość atrybutu automatycznie wygenerowanego klucza.

Zaktualizuj określone pola

Jednoczesne zapisywanie do określonych elementów podrzędnych węzła bez zastępowania innych węzłów podrzędnych, użyj metody UpdateChildren().

Wywołując UpdateChildren(), możesz zaktualizować wartości podrzędne niższego poziomu przez i podaj ścieżkę dostępu do klucza. Jeśli dane są przechowywane w wielu lokalizacjach na potrzeby skalowania możesz zaktualizować wszystkie wystąpienia tych danych za pomocą funkcji rozpowszechnianie danych. Na przykład plik gra może mieć klasę LeaderboardEntry podobną do tej:

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

Aby utworzyć ocenę LeaderboardEntry i jednocześnie zaktualizować ją do najnowszej oceny źródła treści i własnej listy wyników użytkownika, gra używa następującego kodu:

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

W tym przykładzie użyto typu PushChild() do utworzenia wpisu w węźle zawierającym wpisy dla wszystkich użytkowników w organizacji /scores/$key oraz jednocześnie pobieraj klucz za pomocą polecenia key() Za pomocą klucza można utworzyć drugi wpis w zdobywa punkty w grupie /user-scores/$userid/$key.

Korzystając z tych ścieżek, można wprowadzać zmiany w wielu lokalizacjach jednocześnie drzewo JSON z jednym wywołaniem UpdateChildren(), na przykład utworzy nowy wpis w obu lokalizacjach. Równoczesne aktualizacje sprawiły, są niepodzielne: albo wszystkie aktualizacje zakończą się sukcesem, albo wszystkie aktualizacje kończą się niepowodzeniem.

Usuń dane

Najprostszym sposobem usunięcia danych jest wywołanie funkcji RemoveValue() w odniesieniu do lokalizacji danych.

Możesz też usunąć element, określając null Variant jako wartość innego zapisu , na przykład SetValue() lub UpdateChildren(). Możesz użyć tej technika z użyciem UpdateChildren() umożliwiająca usunięcie wielu elementów podrzędnych w 1 interfejsie API .

Kontroluj, kiedy dane są udostępniane.

Aby dowiedzieć się, kiedy dane są przekazywane na serwer Bazy danych czasu rzeczywistego Firebase, sprawdź aby osiągnąć sukces w przyszłości.

Zapisywanie danych jako transakcji

Podczas pracy z danymi, które mogły zostać uszkodzone w wyniku równoczesnej pracy takich jak liczniki przyrostowe, możesz użyć funkcji operacji transakcji. Nadaj tej operacji funkcję DoTransaction. Ta funkcja aktualizacji pobiera bieżący stan danych jako argument i zwraca nowy pożądany stan które chcesz napisać. Jeśli inny klient zapisze dane w tej lokalizacji przed nowa wartość została zapisana, funkcja aktualizacji jest wywoływana ponownie z użyciem nową bieżącą wartość, a zapis jest ponawiany.

Na przykład w grze można zezwolić użytkownikom na aktualizowanie tabeli wyników pięć najwyższych wyników:

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

Użycie transakcji zapobiega nieprawidłowej tabeli wyników, jeśli jest ich wiele użytkownicy rejestrują wyniki w tym samym czasie albo klient ma nieaktualne dane. Jeśli transakcja została odrzucona, serwer zwraca bieżącą wartość klientowi, , co powoduje ponowne uruchomienie transakcji ze zaktualizowaną wartością. Powtarza się do momentu transakcja została zaakceptowana lub dokonano zbyt wielu prób.

Zapisuj dane offline

Jeśli klient utraci połączenie sieciowe, aplikacja będzie nadal działać .

Każdy klient połączony z bazą danych Firebase ma własną wersję wewnętrzną wszystkich aktywnych danych. Podczas zapisywania danych są one zapisywane w tej wersji lokalnej . Klient Firebase następnie synchronizuje te dane ze zdalną bazą danych. z serwerami Google i innymi klientami w ramach „najlepszych starań”, podstaw.

W rezultacie wszystkie zapisy w bazie danych wywołują zdarzenia lokalne natychmiast, przed jakiekolwiek dane są zapisywane na serwerze. Oznacza to, że aplikacja pozostaje niezależnie od opóźnienia sieciowego czy połączenia.

Po przywróceniu połączenia aplikacja otrzyma odpowiedni zestaw zdarzeń, aby klient synchronizował się z bieżącym stanem serwera bez konieczności napisać dowolny niestandardowy kod.

Następne kroki