Menyimpan Data

Cara Menyimpan Data

PUT Menulis atau mengganti data ke jalur yang ditentukan, seperti fireblog/users/user1/<data>
PATCH Memperbarui sebagian kunci untuk sebuah jalur yang ditetapkan tanpa mengganti semua data.
POST Menambahkan ke daftar data dalam database Firebase kita. Setiap kali kita mengirim permintaan POST, klien Firebase akan menghasilkan kunci yang unik, seperti fireblog/users/<unique-id>/<data>
DELETE Menghapus data dari referensi database Firebase yang ditentukan.

Menulis Data dengan PUT

Operasi tulis dasar melalui REST API adalah PUT. Untuk mendemonstrasikan penyimpanan data, kita akan mem-build aplikasi blogging dengan postingan dan pengguna. Semua data untuk aplikasi akan disimpan di jalur `fireblog`, di URL database Firebase `https://docs-examples.firebaseio.com/fireblog`.

Mari kita mulai dengan menyimpan beberapa data pengguna ke database Firebase. Kita akan menyimpan setiap pengguna dengan nama pengguna yang unik, dan kita juga akan menyimpan nama lengkap serta tanggal lahir mereka. Karena setiap pengguna akan memiliki nama pengguna yang unik, sebaiknya gunakan PUT, bukan POST, karena kita telah memiliki kunci dan tidak perlu membuat kunci baru.

Dengan PUT, kita bisa menulis string, angka, boolean, array atau sembarang objek JSON ke database Firebase kita. Dalam hal ini kita akan meneruskan sebuah objek ke database Firebase:

curl -X PUT -d '{
  "alanisawesome": {
    "name": "Alan Turing",
    "birthday": "June 23, 1912"
  }
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'

Ketika objek JSON disimpan ke database, properti objek secara otomatis dipetakan ke lokasi turunan secara bertingkat. Jika kita menuju ke node yang baru dibuat, kita akan melihat nilai "Alan Turing". Kita juga bisa menyimpan data secara langsung ke lokasi turunan:

curl -X PUT -d '"Alan Turing"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/name.json'
curl -X PUT -d '"June 23, 1912"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/birthday.json'

Kedua contoh di atas, yakni menulis nilai secara bersamaan dengan sebuah objek dan menuliskannya secara terpisah ke lokasi turunan, mengakibatkan data yang sama disimpan ke database Firebase kita:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing"
    }
  }
}

Permintaan yang berhasil akan ditunjukkan oleh kode status HTTP 200 OK, dan responsnya akan berisi data yang kita tuliskan ke database. Contoh pertama hanya akan memicu satu peristiwa pada klien yang mengamati data, sedangkan contoh kedua akan memicu dua peristiwa. Perlu diperhatikan bahwa jika data sudah ada di jalur "users", metode pertama akan menimpa data tersebut, tetapi metode kedua hanya akan mengubah nilai dari setiap node turunan yang terpisah dan tidak mengubah turunan lainnya. PUT setara dengan set() di JavaScript SDK.

Memperbarui Data dengan PATCH

Dengan permintaan PATCH, kita dapat memperbarui turunan tertentu di sebuah lokasi tanpa menimpa data yang ada. Mari kita tambahkan nama panggilan Turing ke data penggunanya dengan permintaan PATCH:

curl -X PATCH -d '{
  "nickname": "Alan The Machine"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

Permintaan di atas akan menuliskan nickname ke objek alanisawesome tanpa menghapus turunan name atau birthday. Perlu diperhatikan bahwa jika permintaan PUT telah dibuat di sini, name dan birthday sudah akan dihapus karena keduanya tidak tercantum dalam permintaan ini. Data dalam database Firebase sekarang terlihat seperti ini:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    }
  }
}

Permintaan yang berhasil akan ditunjukkan oleh kode status HTTP 200 OK, dan responsnya akan berisi data yang telah diperbarui yang dituliskan ke database.

Firebase juga mendukung pembaruan multijalur. Artinya, PATCH kini dapat memperbarui nilai di beberapa lokasi dalam database Firebase secara bersamaan. Ini adalah fitur canggih yang akan membantu Anda melakukan denormalisasi data. Dengan pembaruan multijalur, kita dapat menambahkan nama panggilan untuk Alan dan Grace secara bersamaan:

curl -X PATCH -d '{
  "alanisawesome/nickname": "Alan The Machine",
  "gracehopper/nickname": "Amazing Grace"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Setelah pembaruan ini, nama panggilan Alan dan Grace akan ditambahkan:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "date_of_birth": "December 9, 1906",
      "full_name": "Grace Hopper",
      "nickname": "Amazing Grace"
    }
  }
}

Perhatikan bahwa mencoba memperbarui objek dengan menulis objek beserta jalurnya akan menghasilkan perilaku yang berbeda. Mari kita lihat apa yang terjadi jika kita mencoba memperbarui Grace dan Alan dengan cara ini:

curl -X PATCH -d '{
  "alanisawesome": {"nickname": "Alan The Machine"},
  "gracehopper": {"nickname": "Amazing Grace"}
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Cara ini menghasilkan perilaku yang berbeda, yaitu menimpa seluruh node /fireblog/users:

{
  "users": {
    "alanisawesome": {
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "nickname": "Amazing Grace"
    }
  }
}

Memperbarui Data dengan Permintaan Kondisional

Anda dapat menggunakan permintaan kondisional, dengan REST yang setara dengan transaksi, untuk memperbarui data sesuai dengan statusnya yang sudah ada. Misalnya, jika Anda ingin meningkatkan penghitung suara positif, dan ingin memastikan jumlah hitungan mencerminkan suara positif dalam jumlah banyak dan simultan secara akurat, gunakan permintaan kondisional untuk menuliskan nilai baru ke penghitung tersebut. Yang terjadi bukannya dua penulisan yang mengubah penghitung ke jumlah yang sama, melainkan salah satu permintaan penulisan gagal sehingga Anda dapat mencoba lagi untuk melakukan permintaan dengan nilai yang baru.
  1. Untuk melakukan permintaan kondisional di suatu lokasi, dapatkan ID unik untuk data saat ini di lokasi tersebut, atau ETag-nya. Jika data berubah di lokasi tersebut, ETag juga akan berubah. Anda dapat meminta ETag dengan metode apa pun selain PATCH. Contoh berikut menggunakan permintaan GET.
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    
    Pemanggilan ETag di header secara khusus akan menampilkan ETag lokasi yang ditentukan dalam respons HTTP.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    10 // Current value of the data at the specified location
    
  2. Sertakan ETag yang ditampilkan dalam permintaan PUT atau DELETE berikutnya, untuk memperbarui data yang secara khusus sesuai dengan nilai ETag tersebut. Dengan mengikuti contoh, untuk memperbarui penghitung menjadi 11, atau 1 angka lebih besar daripada nilai awal yang diambil yaitu 10, dan menggagalkan permintaan jika nilainya tidak lagi sesuai, gunakan kode berikut ini:
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    
    Jika nilai data di lokasi yang ditentukan masih 10, ETag dalam permintaan PUT akan sesuai, dan permintaan berhasil, sehingga menulis 11 ke database.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    Cache-Control: no-cache
    
    11 // New value of the data at the specified location, written by the conditional request
    
    Jika lokasi tidak lagi sesuai dengan ETag, yang mungkin terjadi jika pengguna lain menulis nilai baru ke database, permintaan akan gagal tanpa menulis ke lokasi tersebut. Respons yang ditampilkan mencakup ETag dan nilai baru.
    HTTP/1.1 412 Precondition Failed
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    12 // New value of the data at the specified location
    
  3. Gunakan informasi baru tersebut jika Anda memutuskan untuk mencoba lagi permintaan tersebut. Realtime Database tidak akan otomatis mencoba lagi permintaan kondisional yang telah gagal. Namun, Anda bisa menggunakan ETag dan nilai baru untuk membuat permintaan kondisional baru dengan informasi yang ditampilkan oleh respons gagal.

Permintaan kondisional berbasis REST menerapkan standar if-match HTTP. Namun, permintaan tersebut berbeda dari permintaan standar dalam hal berikut:

  • Anda hanya bisa menyediakan satu nilai ETag untuk setiap permintaan if-match, tidak dalam jumlah banyak.
  • Meskipun menurut standar ETag akan ditampilkan dengan semua permintaan, Realtime Database hanya akan menampilkan ETag dengan permintaan yang menyertakan header X-Firebase-ETag. Cara ini dapat mengurangi biaya penagihan untuk permintaan standar.

Permintaan kondisional mungkin juga lebih lambat dari permintaan REST biasa.

Menyimpan Daftar Data

Untuk membuat kunci berbasis stempel waktu yang unik untuk setiap turunan yang ditambahkan ke referensi database Firebase, kita dapat mengirimkan permintaan POST. Untuk jalur users, sebaiknya tetapkan kunci kita sendiri karena setiap pengguna memiliki nama pengguna yang unik. Namun, ketika pengguna menambahkan postingan blog ke aplikasi, kita akan menggunakan permintaan POST untuk otomatis membuat kunci bagi setiap postingan blog:

curl -X POST -d '{
  "author": "alanisawesome",
  "title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'

Jalur posts kita sekarang memiliki data berikut:

{
  "posts": {
    "-JSOpn9ZC54A4P4RoqVa": {
      "author": "alanisawesome",
      "title": "The Turing Machine"
    }
  }
}

Perlu diperhatikan bahwa kunci -JSOpn9ZC54A4P4RoqVa otomatis dibuat untuk kita karena telah menggunakan permintaan POST. Permintaan yang sukses akan ditunjukkan oleh kode status HTTP 200 OK, dan responsnya akan berisi kunci data baru yang telah ditambahkan:

{"name":"-JSOpn9ZC54A4P4RoqVa"}

Menghapus Data

Untuk menghapus data dari database, kita bisa mengirim permintaan DELETE dengan URL jalur yang berisi data yang ingin dihapus. Berikut contoh untuk menghapus Alan dari jalur users:

curl -X DELETE \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

Permintaan DELETE yang berhasil akan ditunjukkan oleh kode status HTTP 200 OK dengan respons yang berisi null JSON.

Parameter URI

REST API menerima parameter URI berikut ketika menulis data ke database:

auth

Parameter permintaan auth mengizinkan akses ke data yang dilindungi oleh Aturan Keamanan Firebase Realtime Database, dan didukung oleh semua jenis permintaan. Argumennya bisa berupa rahasia aplikasi Firebase kita atau token autentikasi, yang akan kita bahas di bagian otorisasi pengguna. Dalam contoh berikut, kita akan mengirimkan permintaan POST dengan parameter auth, dengan CREDENTIAL sebagai rahasia aplikasi Firebase kita atau token autentikasi:

curl -X POST -d '{"Authenticated POST request"}' \
  'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

print

Parameter print dapat digunakan untuk menentukan format respons kita dari database. Jika print=pretty ditambahkan ke permintaan, data akan ditampilkan dalam format yang dapat dibaca manusia. print=pretty didukung oleh permintaan GET, PUT, POST, PATCH, dan DELETE.

Untuk menyembunyikan output dari server saat menulis data, kita dapat menambahkan print=silent ke permintaan. Respons yang dihasilkan akan kosong dan ditunjukkan oleh kode status HTTP 204 No Content jika permintaan tersebut berhasil. print=silent didukung oleh permintaan GET, PUT, POST, dan PATCH.

Menulis Nilai Server

Nilai server dapat ditulis pada suatu lokasi menggunakan nilai placeholder, yang berupa objek dengan satu kunci ".sv". Nilai untuk kunci tersebut adalah jenis nilai server yang ingin kita tetapkan. Misalnya, untuk menetapkan stempel waktu saat pengguna dibuat, kita bisa melakukan hal berikut:

curl -X PUT -d '{".sv": "timestamp"}' \
  'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'

"timestamp" adalah satu-satunya nilai server yang didukung, dan merupakan waktu sejak epoch UNIX dalam satuan milidetik.

Meningkatkan Performa Tulis

Jika kita menulis data dalam jumlah besar ke database, kita dapat menggunakan parameter print=silent untuk meningkatkan performa tulis dan mengurangi penggunaan bandwidth. Pada perilaku tulis normal, server merespons dengan data JSON yang ditulis. Saat print=silent ditentukan, server akan segera menutup koneksi begitu data diterima sehingga mengurangi penggunaan bandwidth.

Jika kita membuat banyak permintaan ke database, kita bisa menggunakan kembali koneksi HTTPS dengan mengirimkan permintaan Keep-Alive pada header HTTP.

Kondisi Error

REST API akan menampilkan kode error dalam situasi berikut:

Kode Status HTTP
400 Permintaan Tidak Valid

Salah satu kondisi error berikut:

  • Tidak dapat mengurai data PUT atau POST.
  • Data PUT atau POST tidak ada.
  • Permintaan mencoba melakukan PUT atau POST pada data yang terlalu besar.
  • Panggilan REST API berisi nama turunan yang tidak valid sebagai bagian dari jalur.
  • Jalur panggilan REST API terlalu panjang.
  • Permintaan berisi nilai server yang tidak dikenal.
  • Indeks untuk kueri tidak ditetapkan dalam Aturan Keamanan Firebase Realtime Database Anda.
  • Permintaan tidak mendukung salah satu parameter kueri yang ditentukan.
  • Permintaan mencampur parameter kueri dengan permintaan GET yang dangkal.
401 Tidak Sah

Salah satu kondisi error berikut:

  • Masa berlaku token autentikasi telah berakhir.
  • Token autentikasi yang digunakan dalam permintaan tidak valid.
  • Gagal mengautentikasi dengan access_token.
  • Permintaan melanggar Aturan Keamanan Firebase Realtime Database Anda.
404 Tidak Ditemukan Database Firebase yang ditentukan tidak ditemukan.
500 Error Server Internal Server menampilkan error. Lihat pesan error untuk keterangan lebih lanjut.
503 Layanan Tidak Tersedia Firebase Realtime Database yang ditentukan tidak tersedia untuk sementara, yang berarti permintaan tidak dicoba.

Mengamankan Data

Firebase memiliki bahasa keamanan yang memungkinkan kita menentukan pengguna yang memiliki akses baca dan tulis ke berbagai node data. Anda dapat membaca lebih lanjut tentang hal ini di Aturan Keamanan Realtime Database.

Setelah membahas penyimpanan data, berikutnya kita akan mempelajari cara mengambil data dari database Firebase melalui REST API.