Menyimpan Data dengan Firebase Realtime Database untuk C++

Memulai

Lihat panduan Get Started terlebih dahulu jika Anda belum menyiapkan aplikasi dan akses ke database.

Mendapatkan DatabaseReference

Untuk menulis data ke Database, Anda perlu instance DatabaseReference:

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

Menyimpan Data

Ada 4 metode untuk menulis data ke Firebase Realtime Database:

Metode Penggunaan umum
SetValue() Menulis atau mengganti data ke lokasi yang ditentukan, seperti users/<user-id>/<username>.
PushChild() Menambahkan ke daftar data. Setiap kali Anda memanggil Push(), Firebase menghasilkan kunci unik yang juga dapat digunakan sebagai ID unik, seperti user-scores/<user-id>/<unique-score-id>.
UpdateChildren() Mengupdate beberapa kunci untuk lokasi yang ditetapkan tanpa mengganti semua data.
RunTransaction() Mengupdate data kompleks yang dapat rusak karena update serentak.

Menulis, mengupdate, atau menghapus data pada referensi

Operasi tulis dasar

Untuk operasi tulis dasar, Anda dapat menggunakan SetValue() untuk menyimpan data ke referensi yang ditentukan, sehingga menggantikan data yang ada di lokasi tersebut. Anda dapat menggunakan metode ini untuk meneruskan jenis yang diterima oleh JSON melalui jenis Variasi yang mendukung:

  • Null (ini menghapus data)
  • Bilangan bulat (64-bit)
  • Angka double precision floating point
  • Boolean
  • String
  • Vektor Variasi
  • Peta string ke Variasi

Penggunaan SetValue() seperti ini akan menimpa data di lokasi yang ditentukan, termasuk semua node turunan. Namun, Anda masih dapat mengupdate turunan tanpa menulis ulang seluruh objek. Jika ingin mengizinkan pengguna mengupdate profil mereka, Anda dapat mengupdate nama pengguna seperti berikut:

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

Menambahkan ke daftar data

Gunakan metode PushChild() untuk menambahkan data ke daftar dalam aplikasi multipengguna. Metode PushChild() menghasilkan kunci unik setiap kali turunan baru ditambahkan ke referensi Firebase tertentu. Dengan menggunakan kunci yang dihasilkan secara otomatis ini untuk setiap elemen baru dalam daftar, beberapa klien dapat menambahkan turunan ke lokasi yang sama secara bersamaan tanpa ada konflik tulis. Kunci unik yang dihasilkan oleh PushChild() didasarkan pada stempel waktu, sehingga daftar item otomatis akan diurutkan secara kronologis.

Anda dapat menggunakan referensi data baru yang ditampilkan oleh metode PushChild() untuk mendapatkan nilai kunci turunan yang otomatis dihasilkan atau data kumpulan untuk turunan. Memanggil GetKey() pada referensi PushChild() akan menampilkan nilai kunci yang dihasilkan secara otomatis.

Mengupdate kolom tertentu

Untuk menulis data ke turunan node tertentu secara bersamaan tanpa mengganti node turunan yang lain, gunakan metode UpdateChildren().

Ketika memanggil UpdateChildren(), Anda dapat memperbarui nilai turunan pada tingkat yang lebih rendah dengan menetapkan lokasi untuk kunci tersebut. Jika data disimpan di beberapa lokasi untuk memudahkan penyebaran, Anda dapat mengupdate semua instance dari data tersebut dengan fan-out data. Misalnya, suatu game mungkin memiliki kelas LeaderboardEntry seperti ini:

class LeaderboardEntry {
  std::string uid;
  int score = 0;

 public:
  LeaderboardEntry() {
  }

  LeaderboardEntry(std::string uid, int score) {
    this->uid = uid;
    this->score = score;
  }

  std::map&ltstd::string, Object&gt ToMap() {
    std::map&ltstring, Variant&gt result = new std::map&ltstring, Variant&gt();
    result["uid"] = Variant(uid);
    result["score"] = Variant(score);

    return result;
  }
}

Untuk membuat LeaderboardEntry dan sekaligus mengupdatenya ke feed skor terakhir dan daftar skor pengguna, game tersebut menggunakan kode berikut:

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&ltstd::string, Variant&gt entryValues = entry.ToMap();

  std::map&ltstring, Variant&gt childUpdates = new std::map&ltstring, Variant&gt();
  childUpdates["/scores/" + key] = entryValues;
  childUpdates["/user-scores/" + userId + "/" + key] = entryValues;

  dbref.UpdateChildren(childUpdates);
}

Contoh ini menggunakan PushChild() untuk membuat entri pada node yang memuat entri untuk semua pengguna di /scores/$key, sekaligus mengambil kunci dengan key(). Selanjutnya, kunci tersebut dapat digunakan untuk membuat entri kedua dalam skor pengguna di /user-scores/$userid/$key.

Dengan menggunakan lokasi ini, Anda dapat melakukan update secara simultan ke beberapa lokasi di pohon JSON dengan panggilan tunggal ke UpdateChildren(), sebagaimana contoh ini membuat entri baru di kedua lokasi. Update simultan menjadikan proses ini berjalan secara menyeluruh: semua update berhasil atau semua update gagal.

Menghapus data

Cara termudah untuk menghapus data adalah dengan memanggil RemoveValue() pada referensi ke lokasi data tersebut.

Anda juga dapat menghapus data dengan menentukan Variant null sebagai nilai untuk operasi tulis lainnya seperti SetValue() atau UpdateChildren(). Anda dapat menggunakan teknik ini dengan UpdateChildren() untuk menghapus beberapa turunan dalam 1 panggilan API.

Mengetahui kapan data Anda disimpan.

Untuk mengetahui kapan data Anda disimpan ke server Firebase Realtime Database, periksa keberhasilannya di hasil Future.

Menyimpan data sebagai transaksi

Ketika bekerja dengan data yang bisa rusak karena perubahan serentak, seperti penghitung tambahan, Anda dapat menggunakan operasi transaction. Anda memberikan fungsi DoTransaction pada operasi ini. Fungsi update ini akan mengambil status data saat ini sebagai argumen, dan menampilkan status baru yang diinginkan untuk Anda tulis. Jika klien lainnya melakukan penulisan ke lokasi sebelum nilai yang baru berhasil ditulis, fungsi update Anda akan dipanggil lagi dengan nilai baru saat ini, dan proses tulis akan dicoba ulang.

Misalnya, dalam sebuah game, Anda dapat mengizinkan pengguna untuk mengupdate papan peringkat dengan 5 skor tertinggi:

void AddScoreToLeaders(std::string email,
                       long score,
                       DatabaseReference leaderBoardRef) {
  leaderBoardRef.RunTransaction([](firebase::database::MutableData* mutableData) {
    if (mutableData.children_count() &gt= MaxScores) {
      long minScore = LONG_MAX;
      MutableData *minVal = null;
      std::vector&ltMutableData&gt children = mutableData.children();
      std::vector&ltMutableData&gt::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 &lt minScore) {
          minScore = childScore;
          minVal = &amp*it;
        }
      }
      if (minScore &gt 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&ltstd::string, Variant&gt newScoreMap =
      new std::map&ltstd::string, Variant&gt();
    newScoreMap["score"] = score;
    newScoreMap["email"] = email;
    children.Add(newScoreMap);
    mutableData->set_value(children);
    return kTransactionResultSuccess;
  });
}

Penggunaan transaksi dapat mencegah kesalahan papan peringkat jika beberapa pengguna mencatat skor secara bersamaan atau jika klien memiliki data yang sudah usang. Jika transaksi ditolak, server akan menampilkan nilai saat ini ke klien yang akan menjalankan lagi transaksi tersebut dengan nilai yang diupdate. Proses ini berulang hingga transaksi diterima atau terlalu banyak percobaan dilakukan.

Menulis data secara offline

Jika koneksi jaringan klien terputus, aplikasi Anda akan tetap berfungsi dengan baik.

Setiap klien yang terhubung ke database Firebase menyimpan versi internalnya sendiri dari setiap data aktif. Ketika ditulis, data akan dituliskan ke versi lokal ini terlebih dahulu. Selanjutnya, klien Firebase menyinkronkan data tersebut dengan server database di tempat lain, dan dengan klien lain berdasarkan "upaya terbaik".

Akibatnya, semua operasi tulis ke database akan segera memicu peristiwa lokal, sebelum ada data yang dituliskan ke server. Ini berarti aplikasi Anda akan tetap responsif, apa pun kondisi latensi atau konektivitas jaringannya.

Setelah konektivitas pulih, aplikasi Anda akan menerima kumpulan peristiwa yang tepat, sehingga klien sinkron dengan kondisi server saat ini, tanpa perlu menulis kode khusus apa pun.

Langkah Berikutnya

Kirim masukan tentang...

Butuh bantuan? Kunjungi halaman dukungan kami.