Cloud Functions umożliwia obsługę zdarzeń Cloud Firestore bez konieczności aktualizowania kodu klienta. Zmiany w Cloud Firestore możesz wprowadzać w migawki dokumentu lub Pakiet Admin SDK.
W typowym cyklu życia funkcja Cloud Firestore wykonuje te czynności:
- Czeka na zmiany w danym dokumencie.
- Uruchamia się, gdy wystąpi zdarzenie, i wykonuje swoje zadania.
- Otrzymuje obiekt danych zawierający zrzut danych przechowywanych w określonym dokumencie. W przypadku zdarzeń zapisu lub aktualizacji obiekt danych zawiera 2 migawki, które reprezentują stan danych przed i po wywołaniu zdarzenia.
Odległość między lokalizacją instancji Firestore a lokalizacją może powodować znaczne opóźnienia sieciowe. Aby zoptymalizować wydajność, rozważ określenie lokalizacji funkcji w odpowiednich przypadkach.
Aktywatory funkcji Cloud Firestore
Pakiet SDK Cloud Functions for Firebase eksportuje obiekt functions.firestore
, który umożliwia tworzenie modułów obsługi powiązanych z określonymi zdarzeniami Cloud Firestore.
Typ zdarzenia | Aktywator |
---|---|
onCreate |
Wywoływane, gdy dokument jest zapisany po raz pierwszy. |
onUpdate |
Wyzwalane, gdy dokument już istnieje i jego jakakolwiek wartość ulegnie zmianie. |
onDelete |
Wywoływane po usunięciu dokumentu z danymi. |
onWrite |
Wywoływane po wywołaniu funkcji onCreate , onUpdate lub onDelete . |
Jeśli nie masz jeszcze w projekcie włączonego projektu Cloud Functions for Firebase, przeczytaj Pierwsze kroki: pisanie i wdrażanie pierwszych funkcji aby skonfigurować projekt Cloud Functions for Firebase.
Pisanie funkcji wywoływanych przez Cloud Firestore
Zdefiniuj aktywator funkcji
Aby zdefiniować aktywator Cloud Firestore, podaj ścieżkę dokumentu i typ zdarzenia:
Node.js
const functions = require('firebase-functions');
exports.myFunction = functions.firestore
.document('my-collection/{docId}')
.onWrite((change, context) => { /* ... */ });
Ścieżki dokumentów mogą odwoływać się do konkretnego dokumentu lub do wzorca z symbolami wieloznacznymi.
Określ pojedynczy dokument
Jeśli chcesz wywołać zdarzenie w przypadku dowolnej zmiany w określonym dokumencie: możesz użyć następującej funkcji.
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 });
Określanie grupy dokumentów za pomocą symboli wieloznacznych
Jeśli chcesz dołączyć regułę do grupy dokumentów, takich jak dowolny dokument w
dla określonej kolekcji, a następnie użyj {wildcard}
zamiast
identyfikator dokumentu:
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"} });
W tym przykładzie, gdy zmieni się dowolne pole w dowolnym dokumencie w dokumencie users
, zostanie ono dopasowane
symbol wieloznaczny o nazwie userId
.
Jeśli dokument w kolekcji users
zawiera kolekcje podrzędne i pole w jednej z tych kolekcji
dokument został zmieniony, symbol wieloznaczny userId
nie zostanie wywołany.
Dopasowania zawierające symbole wieloznaczne są wyodrębniane ze ścieżki dokumentu i przechowywane w elemencie context.params
.
Możesz zdefiniować dowolną liczbę symboli wieloznacznych, aby zastąpić jawne identyfikatory zbiorów lub dokumentów, na przykład:
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"} });
Wyzwalacze zdarzeń
Wywoływanie funkcji po utworzeniu nowego dokumentu
Możesz aktywować funkcję uruchamiania za każdym razem, gdy w kolekcji zostanie utworzony nowy dokument
za pomocą modułu obsługi onCreate()
z symbolem wieloznacznym.
Ta przykładowa funkcja wywołuje createUser
za każdym razem, gdy dodawany jest nowy profil użytkownika:
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 ... });
Wywoływanie funkcji po zaktualizowaniu dokumentu
Możesz też uruchomić funkcję, gdy dokument zostanie zaktualizowany, używając funkcji onUpdate()
z symbolem wieloznacznym. Ta przykładowa funkcja wywołuje updateUser
, jeśli użytkownik
zmienia swój profil:
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 ... });
Uruchamianie funkcji po usunięciu dokumentu
Możesz też uruchomić funkcję po usunięciu dokumentu, używając funkcji onDelete()
z symbolem wieloznacznym. W tym przykładzie funkcja deleteUser
jest wywoływana, gdy użytkownik usuwa swój profil:
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 ... });
Aktywowanie funkcji przy wszystkich zmianach w dokumencie
Jeśli nie interesuje Cię typ wywoływanego zdarzenia, możesz nasłuchiwać
zmian w dokumencie Cloud Firestore przy użyciu funkcji onWrite()
za pomocą symbolu wieloznacznego. Ta przykładowa funkcja wywołuje funkcję modifyUser
, jeśli użytkownik zostanie utworzony, zaktualizowany lub usunięty:
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 ... });
Odczytywanie i zapisywanie danych
Po wywołaniu funkcja udostępnia zrzut danych związanych z . Możesz użyć tego snapshotu do odczytu lub zapisu dokumentu, który wywołał zdarzenie, albo użyć pakietu Firebase Admin SDK, aby uzyskać dostęp do innych części bazy danych.
Dane zdarzenia
Odczytywanie danych
Gdy funkcja zostanie wywołana, możesz pobrać dane z zaktualizowanego dokumentu lub dane przed aktualizacją. Poprzednie dane możesz uzyskać, korzystając z klucza change.before.data()
, który zawiera zrzut dokumentu sprzed aktualizacji.
Podobnie change.after.data()
zawiera stan zrzutu dokumentu po aktualizacji.
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(); });
Możesz uzyskać dostęp do właściwości tak samo jak w przypadku każdego innego obiektu. Możesz też użyć funkcji get
, aby uzyskać dostęp do określonych pól:
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');
Zapisywanie danych
Każde wywołanie funkcji jest powiązane z konkretnym dokumentem w bazie danych Cloud Firestore. Dostęp do tego dokumentu uzyskasz jako DocumentReference
w właściwości ref
przechwytywania zwracanego przez funkcję.
To źródło danych (DocumentReference
) pochodzi z:
Pakiet SDK Cloud Firestore Node.js
i obejmuje metody takie jak update()
, set()
i remove()
, dzięki czemu możesz łatwo
modyfikować dokument, który uruchomił tę funkcję.
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}); });
Dane spoza zdarzenia uruchamiającego
Cloud Functions uruchamiać w zaufanym środowisku, co oznacza, że są autoryzowane jako konto usługi w Twoim projekcie. Możesz wykonywać odczyty i zapisy za pomocą pakietu SDK Firebase Admin:
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({ ... });
});
Ograniczenia
Pamiętaj o tych ograniczeniach dotyczących Cloud Firestore w przypadku Cloud Functions:
- Cloud Functions (pierwsza generacja) wymaga istniejącej bazy danych „(domyślna)” w trybie natywnym Firestore. Nie obsługują nazwane bazy danych Cloud Firestore lub tryb Datastore. Użyj konta Cloud Functions (2 generacji), aby skonfigurować zdarzenia w takich przypadkach.
- Zamówienie nie jest gwarantowane. Szybkie zmiany mogą aktywować wywołania funkcji w nieoczekiwanej kolejności.
- Zdarzenia są wysyłane co najmniej raz, ale pojedyncze zdarzenie może spowodować wielokrotne wywołanie funkcji. Unikaj zależnie od mechanika dokładnie raz, funkcji idempotentnych.
- Cloud Firestore w trybie Datastore wymaga Cloud Functions (2 generacji). Cloud Functions (1 generacji) nie obsługują tryb Datastore.
- Aktywator jest powiązany z jedną bazą danych. Nie można utworzyć aktywatora pasującego do wielu baz danych.
- Usunięcie bazy danych nie powoduje automatycznego usunięcia żadnych jej reguł. Wyzwalacz przestaje dostarczać zdarzenia, ale nadal istnieje, dopóki go nie usuniesz.
- Jeśli dopasowane zdarzenie przekracza maksymalny rozmiar żądania, w tagu
zdarzenie może nie zostać dostarczone do domeny Cloud Functions (1 generacji).
- Zdarzenia, które nie zostały dostarczone z powodu rozmiaru żądania, są rejestrowane w logach platformy i wliczane do wykorzystania logów w projekcie.
- Te logi znajdziesz w eksploratorze logów z komunikatem „Zdarzenie nie może dostarczyć do
Funkcja w Cloud Functions z powodu przekroczenia limitu dla 1 generacji...” z
error
wagi. Nazwę funkcji znajdziesz pod polemfunctionName
. Jeśli polereceiveTimestamp
znajduje się jeszcze w ciągu godziny, możesz określić faktycznej treści wydarzenia, odczytując dany dokument z przed sygnaturą czasową i po niej. - Aby ich uniknąć:
- Przeprowadź migrację i przejdź na Cloud Functions (2 generacji)
- zmniejszyć rozmiar dokumentu,
- Usuń Cloud Functions
- Logowanie możesz wyłączyć przy użyciu wykluczeń. Pamiętaj jednak, że zdarzenia naruszające zasady nadal nie zostaną dostarczone.