Dengan Cloud Functions, Anda dapat menangani peristiwa di Cloud Firestore tanpa harus memperbarui kode klien. Anda dapat membuat perubahan pada Cloud Firestore melalui antarmuka ringkasan dokumen atau melalui Admin SDK.
Dalam siklus proses umum, fungsi Cloud Firestore melakukan hal-hal berikut:
- Menunggu perubahan pada dokumen tertentu.
- Terpicu ketika suatu peristiwa terjadi dan menjalankan tugasnya.
- Menerima objek data yang berisi snapshot data yang disimpan dalam dokumen yang ditentukan. Untuk peristiwa operasi tulis atau pembaruan, objek data berisi dua snapshot yang mewakili status data sebelum dan setelah peristiwa pemicu.
Jarak antara lokasi instance Firestore dan lokasi fungsi dapat menyebabkan latensi jaringan yang signifikan. Untuk mengoptimalkan performa, sebaiknya tentukan lokasi fungsi, jika bisa diterapkan.
Pemicu fungsi Cloud Firestore
Cloud Functions for Firebase SDK mengekspor objek functions.firestore
, sehingga Anda dapat membuat pengendali yang terikat dengan peristiwa Cloud 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 Anda belum memiliki 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 oleh Cloud Firestore
Mendefinisikan pemicu fungsi
Untuk mendefinisikan pemicu Cloud 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 Cloud Firestore menggunakan fungsi onWrite()
dengan karakter pengganti. Fungsi contoh ini akan memanggil modifyUser
ketika 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 Cloud Firestore. Anda dapat mengakses dokumen tersebut sebagai DocumentReference
di properti ref
pada snapshot yang ditampilkan ke fungsi Anda.
DocumentReference
ini berasal dari Cloud 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 diotorisasi 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 Cloud Firestore untuk Cloud Functions:
- Cloud Functions (generasi ke-1) hanya dapat digunakan dengan database "(default)" yang sudah dibuat dengan mode native Firestore. Teknologi ini tidak mendukung mode Datastore atau database bernama Cloud Firestore. Gunakan Cloud Functions (generasi ke-2) untuk mengonfigurasi peristiwa dalam kasus tersebut.
- 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.
- Cloud Firestore dalam mode Datastore memerlukan Cloud Functions (generasi ke-2). Cloud Functions (generasi ke-1) tidak mendukung mode Datastore.
- 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 dalam log platform dan diperhitungkan terhadap 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 peristiwa seperti ini, Anda dapat:
- Migrasikan dan upgrade ke Cloud Functions (generasi ke-2)
- Memperkecil dokumen
- Hapus Cloud Functions yang dimaksud
- Anda dapat menonaktifkan logging itu sendiri menggunakan pengecualian, tetapi perhatikan bahwa peristiwa yang melanggar tidak akan dikirim.