Memperluas Firestore dengan Cloud Functions
Dengan Cloud Functions, Anda dapat men-deploy kode Node.js untuk menangani peristiwa yang dipicu oleh perubahan dalam database Firestore. Dengan begitu, Anda dapat menambahkan fungsionalitas sisi server ke aplikasi dengan mudah tanpa harus menjalankan server Anda sendiri.
Untuk contoh kasus penggunaan, lihat Apa yang Dapat Dilakukan dengan Cloud Functions? atau repositori GitHub Contoh Fungsi.
Pemicu fungsi Firestore
Cloud Functions for Firebase SDK mengekspor objek functions.firestore
, sehingga Anda dapat membuat pengendali yang terikat dengan peristiwa Firestore tertentu.
Jenis Peristiwa | Pemicu |
---|---|
onCreate |
Dipicu saat dokumen ditulisi untuk pertama kalinya. |
onUpdate |
Dipicu saat dokumen sudah ada dan nilainya berubah. |
onDelete |
Dipicu saat dokumen yang memuat data dihapus. |
onWrite |
Dipicu saat onCreate , onUpdate , atau onDelete dipicu. |
Jika belum ada project yang diaktifkan untuk Cloud Functions for Firebase, baca Memulai: Menulis dan Men-deploy Fungsi Pertama Anda untuk mengonfigurasi dan menyiapkan project Cloud Functions for Firebase.
Menulis fungsi yang dipicu Firestore
Mendefinisikan pemicu fungsi
Untuk menentukan pemicu Firestore, tentukan jalur dokumen dan jenis peristiwa:
Node.js
const functions = require('firebase-functions');
exports.myFunction = functions.firestore
.document('my-collection/{docId}')
.onWrite((change, context) => { /* ... */ });
Jalur dokumen dapat merujuk pada dokumen tertentu atau pola karakter pengganti.
Menentukan satu dokumen
Jika ingin memicu suatu peristiwa untuk perubahan apa pun pada dokumen tertentu, Anda dapat menggunakan fungsi berikut.
Node.js
// Listen for any change on document `marie` in collection `users` exports.myFunctionName = functions.firestore .document('users/marie').onWrite((change, context) => { // ... Your code here });
Menentukan grup dokumen menggunakan karakter pengganti
Jika ingin menambahkan pemicu ke grup dokumen, seperti dokumen dalam koleksi tertentu, gunakan {wildcard}
sebagai pengganti ID dokumen:
Node.js
// Listen for changes in all documents in the 'users' collection exports.useWildcard = functions.firestore .document('users/{userId}') .onWrite((change, context) => { // If we set `/users/marie` to {name: "Marie"} then // context.params.userId == "marie" // ... and ... // change.after.data() == {name: "Marie"} });
Dalam contoh ini, saat kolom dalam dokumen pada users
diubah, sistem akan mencocokkannya dengan karakter pengganti yang disebut userId
.
Jika dokumen dalam users
memiliki subkoleksi, dan kolom di salah satu dokumen subkoleksi tersebut diubah, karakter pengganti userId
tidak akan terpicu.
Kecocokan karakter pengganti diekstrak dari jalur dokumen dan disimpan ke dalam context.params
.
Anda dapat mendefinisikan sebanyak mungkin karakter pengganti yang diinginkan untuk menggantikan ID dokumen atau koleksi eksplisit, misalnya:
Node.js
// Listen for changes in all documents in the 'users' collection and all subcollections exports.useMultipleWildcards = functions.firestore .document('users/{userId}/{messageCollectionId}/{messageId}') .onWrite((change, context) => { // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then // context.params.userId == "marie"; // context.params.messageCollectionId == "incoming_messages"; // context.params.messageId == "134"; // ... and ... // change.after.data() == {body: "Hello"} });
Pemicu Peristiwa
Memicu fungsi saat dokumen baru dibuat
Anda dapat memicu fungsi agar aktif setiap kali ada dokumen baru yang dibuat dalam koleksi menggunakan pengendali onCreate()
dengan karakter pengganti.
Fungsi contoh ini akan memanggil createUser
setiap kali profil pengguna baru ditambahkan:
Node.js
exports.createUser = functions.firestore .document('users/{userId}') .onCreate((snap, context) => { // Get an object representing the document // e.g. {'name': 'Marie', 'age': 66} const newValue = snap.data(); // access a particular field as you would any JS property const name = newValue.name; // perform desired operations ... });
Memicu fungsi saat dokumen diperbarui
Anda juga dapat memicu fungsi agar aktif saat dokumen diperbarui menggunakan fungsi onUpdate()
dengan karakter pengganti. Fungsi contoh ini akan memanggil updateUser
jika pengguna mengubah profilnya:
Node.js
exports.updateUser = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Get an object representing the document // e.g. {'name': 'Marie', 'age': 66} const newValue = change.after.data(); // ...or the previous value before this update const previousValue = change.before.data(); // access a particular field as you would any JS property const name = newValue.name; // perform desired operations ... });
Memicu fungsi saat dokumen dihapus
Anda juga dapat memicu fungsi saat dokumen dihapus menggunakan fungsi onDelete()
dengan karakter pengganti. Fungsi contoh ini akan memanggil deleteUser
ketika pengguna menghapus profilnya:
Node.js
exports.deleteUser = functions.firestore .document('users/{userID}') .onDelete((snap, context) => { // Get an object representing the document prior to deletion // e.g. {'name': 'Marie', 'age': 66} const deletedValue = snap.data(); // perform desired operations ... });
Memicu fungsi untuk semua perubahan pada dokumen
Jika tidak mementingkan jenis peristiwa yang diaktifkan, Anda dapat memproses semua perubahan dalam dokumen Firestore menggunakan fungsi onWrite()
dengan karakter pengganti. Fungsi contoh ini akan memanggil modifyUser
jika pengguna dibuat, diperbarui, atau dihapus:
Node.js
exports.modifyUser = functions.firestore .document('users/{userID}') .onWrite((change, context) => { // Get an object with the current document value. // If the document does not exist, it has been deleted. const document = change.after.exists ? change.after.data() : null; // Get an object with the previous document value (for update or delete) const oldDocument = change.before.data(); // perform desired operations ... });
Membaca dan Menulis Data
Jika dipicu, suatu fungsi akan menghasilkan snapshot data yang terkait dengan peristiwa tersebut. Anda dapat menggunakan snapshot ini untuk membaca atau menulis dokumen yang memicu peristiwa tersebut, atau menggunakan Firebase Admin SDK untuk mengakses bagian lain database Anda.
Data Peristiwa
Membaca Data
Saat sebuah fungsi dipicu, Anda mungkin ingin mendapatkan data dari dokumen sesudah atau sebelum pembaruan. Anda bisa mendapatkan data sebelumnya menggunakan change.before.data()
, yang berisi snapshot dokumen sebelum pembaruan.
Demikian pula, change.after.data()
berisi status snapshot dokumen setelah pembaruan.
Node.js
exports.updateUser2 = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Get an object representing the current document const newValue = change.after.data(); // ...or the previous value before this update const previousValue = change.before.data(); });
Anda dapat mengakses properti sebagaimana Anda mengakses properti pada objek lainnya. Atau, Anda dapat menggunakan fungsi get
untuk mengakses kolom tertentu:
Node.js
// Fetch data using standard accessors const age = snap.data().age; const name = snap.data()['name']; // Fetch data using built in accessor const experience = snap.get('experience');
Menulis Data
Setiap pemanggilan fungsi dikaitkan dengan dokumen tertentu dalam database Firestore. Anda dapat mengakses dokumen tersebut sebagai DocumentReference
di properti ref
pada snapshot yang ditampilkan ke fungsi Anda.
DocumentReference
ini berasal dari
Firestore Node.js SDK
dan mencakup berbagai metode seperti update()
, set()
, dan remove()
sehingga Anda dapat dengan mudah
mengubah dokumen yang memicu fungsi tersebut.
Node.js
// Listen for updates to any `user` document. exports.countNameChanges = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Retrieve the current and previous value const data = change.after.data(); const previousData = change.before.data(); // We'll only update if the name has changed. // This is crucial to prevent infinite loops. if (data.name == previousData.name) { return null; } // Retrieve the current count of name changes let count = data.name_change_count; if (!count) { count = 0; } // Then return a promise of a set operation to update the count return change.after.ref.set({ name_change_count: count + 1 }, {merge: true}); });
Data di luar peristiwa pemicu
Cloud Functions dijalankan dalam lingkungan tepercaya, yang berarti diberi otorisasi sebagai akun layanan di project Anda. Anda dapat melakukan pembacaan dan penulisan menggunakan Firebase Admin SDK:
Node.js
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.writeToFirestore = functions.firestore
.document('some/doc')
.onWrite((change, context) => {
db.doc('some/otherdoc').set({ ... });
});
Batasan
Perhatikan batasan berikut untuk pemicu Firestore untuk Cloud Functions:
- Pengurutan tidak dijamin. Perubahan cepat dapat memicu pemanggilan fungsi dalam urutan yang tidak terduga.
- Peristiwa dikirim setidaknya satu kali, tetapi satu peristiwa dapat menghasilkan beberapa pemanggilan fungsi. Hindari mengandalkan mekanisme tepat satu kali, dan tulis fungsi idempoten.
- Firestore dalam mode Datastore memerlukan Cloud Functions (generasi ke-2). Cloud Functions (generasi ke-1) tidak mendukung mode Datastore.
- Cloud Functions (generasi ke-1) hanya berfungsi dengan database "(default)" dan tidak mendukung database bernama Firestore. Gunakan Cloud Functions (generasi ke-2) untuk mengonfigurasi peristiwa untuk database bernama.
- Pemicu dikaitkan dengan satu database. Anda tidak dapat membuat pemicu yang cocok dengan beberapa database.
- Menghapus database tidak secara otomatis menghapus pemicu untuk database tersebut. Pemicu berhenti mengirim peristiwa, tetapi akan tetap ada sampai Anda menghapus pemicu.
- Jika peristiwa yang cocok melebihi ukuran permintaan maksimum, peristiwa tersebut mungkin tidak akan dikirim ke Cloud Functions (generasi ke-1).
- Peristiwa yang tidak terkirim karena ukuran permintaan akan dicatat ke dalam log dalam log platform dan akan diperhitungkan dalam penggunaan log untuk project.
- Anda dapat menemukan log ini di Logs Explorer dengan pesan "Event dapat mengirim ke
Cloud function karena ukuran melebihi batas untuk generasi ke-1..." dengan tingkat keparahan
error
. Anda dapat menemukan nama fungsi di bawah kolomfunctionName
. Jika kolomreceiveTimestamp
masih berada dalam waktu satu jam dari sekarang, Anda dapat menyimpulkan konten peristiwa yang sebenarnya dengan membaca dokumen yang dimaksud menggunakan snapshot sebelum dan setelah stempel waktu. - Untuk menghindari ritme tersebut, Anda dapat:
- Melakukan migrasi dan upgrade ke Cloud Functions (generasi ke-2)
- Perkecil dokumen
- Hapus Cloud Functions yang dimaksud
- Anda dapat menonaktifkan logging itu sendiri menggunakan pengecualian, tetapi perhatikan bahwa peristiwa yang melanggar tetap tidak akan dikirim.