Mit Cloud Functions können Sie Code bereitstellen, um ausgelöste Ereignisse zu verarbeiten durch Änderungen in Ihrer Cloud Firestore-Datenbank. Auf diese Weise können Sie problemlos serverseitige Funktionen zu Ihrer App hinzufügen, ohne Ihre eigenen Server zu betreiben.
Cloud Functions (2. Generation)
Bereitgestellt von Cloud Run und Eventarc, Cloud Functions for Firebase (2. Generation) bietet leistungsstärkere Infrastruktur, erweiterte Kontrolle über Leistung und Skalierbarkeit und mehr die Funktionslaufzeit. Weitere Informationen zur 2nd gen finden Sie unter Cloud Functions for Firebase (2. Generation) Weitere Informationen zur 1. Generation erhalten, siehe Cloud Firestore mit Cloud Functions erweitern
Cloud Firestore-Funktionstrigger
Das Cloud Functions for Firebase SDK exportiert die folgenden Cloud Firestore-Ereignistrigger, mit denen Sie Handler erstellen können, die mit bestimmten Cloud Firestore-Ereignissen verknüpft sind:
Node.js
Ereignistyp | Trigger |
---|---|
onDocumentCreated |
Wird ausgelöst, wenn ein Dokument zum ersten Mal beschrieben wird. |
onDocumentUpdated |
Wird ausgelöst, wenn ein Dokument bereits existiert und sich ein Wert geändert hat. |
onDocumentDeleted |
Wird ausgelöst, wenn ein Dokument gelöscht wird |
onDocumentWritten |
Wird ausgelöst, wenn onDocumentCreated , onDocumentUpdated oder onDocumentDeleted ausgelöst wird. |
onDocumentCreatedWithAuthContext |
onDocumentCreated mit zusätzlichen Authentifizierungsinformationen |
onDocumentWrittenWithAuthContext |
onDocumentWritten durch zusätzliche Authentifizierungsinformationen |
onDocumentDeletedWithAuthContext |
onDocumentDeleted durch zusätzliche Authentifizierungsinformationen |
onDocumentUpdatedWithAuthContext |
onDocumentUpdated durch zusätzliche Authentifizierungsinformationen |
Python (Vorabversion)
Ereignistyp | Trigger |
---|---|
on_document_created |
Wird ausgelöst, wenn ein Dokument zum ersten Mal beschrieben wird. |
on_document_updated |
Wird ausgelöst, wenn ein Dokument bereits existiert und sich ein Wert geändert hat. |
on_document_deleted |
Wird ausgelöst, wenn ein Dokument gelöscht wird |
on_document_written |
Wird ausgelöst, wenn on_document_created , on_document_updated oder on_document_deleted ausgelöst wird. |
on_document_created_with_auth_context |
on_document_created mit zusätzlichen Authentifizierungsinformationen |
on_document_updated_with_auth_context |
on_document_updated durch zusätzliche Authentifizierungsinformationen |
on_document_deleted_with_auth_context |
on_document_deleted durch zusätzliche Authentifizierungsinformationen |
on_document_written_with_auth_context |
on_document_written durch zusätzliche Authentifizierungsinformationen |
Nur Cloud Firestore-Ereignisse werden ausgelöst zu Dokumentänderungen. Eine Aktualisierung eines Cloud Firestore-Dokuments, in dem Daten unverändert ist (ein No-Op-Schreibvorgang) generiert kein Aktualisierungs- oder Schreibereignis. Es ist ist es nicht möglich, bestimmten Feldern Ereignisse hinzuzufügen.
Wenn Sie noch kein Projekt für Cloud Functions for Firebase aktiviert haben, lesen Sie Erste Schritte mit Cloud Functions for Firebase (2. Generation) um Ihr Cloud Functions for Firebase-Projekt zu konfigurieren und einzurichten.
Cloud Firestore-ausgelöste Funktionen schreiben
Funktions-Trigger definieren
Geben Sie zum Definieren eines Cloud Firestore-Triggers einen Dokumentpfad und einen Ereignistyp an:
Node.js
import {
onDocumentWritten,
onDocumentCreated,
onDocumentUpdated,
onDocumentDeleted,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.myfunction = onDocumentWritten("my-collection/{docId}", (event) => {
/* ... */
});
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_created,
on_document_deleted,
on_document_updated,
on_document_written,
Event,
Change,
DocumentSnapshot,
)
@on_document_created(document="users/{userId}")
def myfunction(event: Event[DocumentSnapshot]) -> None:
Dokumentpfade können entweder auf ein bestimmtes Dokument oder ein Platzhaltermuster verweisen.
Einzelnes Dokument angeben
Wenn Sie ein Ereignis für beliebige Änderungen an einem bestimmten Dokument auslösen möchten, können Sie die folgende Funktion verwenden.
Node.js
import {
onDocumentWritten,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.myfunction = onDocumentWritten("users/marie", (event) => {
// Your code here
});
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_written,
Event,
Change,
DocumentSnapshot,
)
@on_document_written(document="users/marie")
def myfunction(event: Event[Change[DocumentSnapshot]]) -> None:
Mithilfe von Platzhaltern eine Gruppe von Dokumenten angeben
Wenn Sie einen Trigger an eine Gruppe von Dokumenten anhängen möchten, z. B. an ein Dokument in einer bestimmten Sammlung, verwenden Sie {wildcard}
anstelle der Dokument-ID:
Node.js
import {
onDocumentWritten,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.myfunction = onDocumentWritten("users/{userId}", (event) => {
// If we set `/users/marie` to {name: "Marie"} then
// event.params.userId == "marie"
// ... and ...
// event.data.after.data() == {name: "Marie"}
});
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_written,
Event,
Change,
DocumentSnapshot,
)
@on_document_written(document="users/{userId}")
def myfunction(event: Event[Change[DocumentSnapshot]]) -> None:
# If we set `/users/marie` to {name: "Marie"} then
event.params["userId"] == "marie" # True
# ... and ...
event.data.after.to_dict() == {"name": "Marie"} # True
Wenn in diesem Beispiel ein Feld in einem Dokument im Verzeichnis users
geändert wird, entspricht es einem Platzhalter namens userId
.
Wenn ein Dokument in users
untergeordnete Sammlungen und ein Feld in einer dieser Sammlungen hat
Untersammlungen Dokumente geändert werden, wird der Platzhalter userId
nicht ausgelöst.
Platzhalterübereinstimmungen werden aus dem Dokumentpfad extrahiert und in event.params
gespeichert.
Sie können beliebig viele Platzhalter festlegen, um explizite Sammlungs- oder Dokument-IDs zu ersetzen. Beispiel:
Node.js
import {
onDocumentWritten,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.myfunction = onDocumentWritten("users/{userId}/{messageCollectionId}/{messageId}", (event) => {
// If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
// event.params.userId == "marie";
// event.params.messageCollectionId == "incoming_messages";
// event.params.messageId == "134";
// ... and ...
// event.data.after.data() == {body: "Hello"}
});
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_written,
Event,
Change,
DocumentSnapshot,
)
@on_document_written(document="users/{userId}/{messageCollectionId}/{messageId}")
def myfunction(event: Event[Change[DocumentSnapshot]]) -> None:
# If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
event.params["userId"] == "marie" # True
event.params["messageCollectionId"] == "incoming_messages" # True
event.params["messageId"] == "134" # True
# ... and ...
event.data.after.to_dict() == {"body": "Hello"}
Der Trigger muss immer auf ein Dokument verweisen, auch wenn Sie einen Platzhalter verwenden.
users/{userId}/{messageCollectionId}
ist beispielsweise ungültig, weil {messageCollectionId}
ist eine Sammlung. users/{userId}/{messageCollectionId}/{messageId}
ist jedoch
gültig, weil {messageId}
immer auf ein Dokument verweist.
Ereignis-Trigger
Beim Erstellen eines neuen Dokuments eine Funktion auslösen
Sie können festlegen, dass eine Funktion jedes Mal ausgelöst wird, wenn ein neues Dokument in einer Sammlung erstellt wird. Diese Beispielfunktion wird jedes Mal ausgelöst, wenn ein neues Nutzerprofil hinzugefügt wird:
Node.js
import {
onDocumentCreated,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.createuser = onDocumentCreated("users/{userId}", (event) => {
// Get an object representing the document
// e.g. {'name': 'Marie', 'age': 66}
const snapshot = event.data;
if (!snapshot) {
console.log("No data associated with the event");
return;
}
const data = snapshot.data();
// access a particular field as you would any JS property
const name = data.name;
// perform more operations ...
});
Verwenden Sie onDocumentCreatedWithAuthContext
, um zusätzliche Authentifizierungsinformationen zu erhalten.
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_created,
Event,
DocumentSnapshot,
)
@on_document_created(document="users/{userId}")
def myfunction(event: Event[DocumentSnapshot]) -> None:
# Get a dictionary representing the document
# e.g. {'name': 'Marie', 'age': 66}
new_value = event.data.to_dict()
# Access a particular field as you would any dictionary
name = new_value["name"]
# Perform more operations ...
Funktion auslösen, wenn ein Dokument aktualisiert wird
Sie können auch festlegen, dass eine Funktion ausgelöst wird, wenn ein Dokument aktualisiert wird. Diese Beispielfunktion wird ausgelöst, wenn ein Nutzer sein Profil ändert:
Node.js
import {
onDocumentUpdated,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.updateuser = onDocumentUpdated("users/{userId}", (event) => {
// Get an object representing the document
// e.g. {'name': 'Marie', 'age': 66}
const newValue = event.data.after.data();
// access a particular field as you would any JS property
const name = newValue.name;
// perform more operations ...
});
Verwenden Sie onDocumentUpdatedWithAuthContext
, um zusätzliche Authentifizierungsinformationen zu erhalten.
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_updated,
Event,
Change,
DocumentSnapshot,
)
@on_document_updated(document="users/{userId}")
def myfunction(event: Event[Change[DocumentSnapshot]]) -> None:
# Get a dictionary representing the document
# e.g. {'name': 'Marie', 'age': 66}
new_value = event.data.after.to_dict()
# Access a particular field as you would any dictionary
name = new_value["name"]
# Perform more operations ...
Funktion auslösen, wenn ein Dokument gelöscht wird
Sie können eine Funktion auch auslösen, wenn ein Dokument gelöscht wird. Dieses Beispiel wird ausgelöst, wenn ein Nutzer sein Nutzerprofil löscht:
Node.js
import {
onDocumentDeleted,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.deleteuser = onDocumentDeleted("users/{userId}", (event) => {
// Get an object representing the document
// e.g. {'name': 'Marie', 'age': 66}
const snap = event.data;
const data = snap.data();
// perform more operations ...
});
Verwenden Sie onDocumentDeletedWithAuthContext
, um zusätzliche Authentifizierungsinformationen zu erhalten.
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_deleted,
Event,
DocumentSnapshot,
)
@on_document_deleted(document="users/{userId}")
def myfunction(event: Event[DocumentSnapshot|None]) -> None:
# Perform more operations ...
Funktion für alle Änderungen an einem Dokument auslösen
Wenn Ihnen die Art des ausgelösten Ereignisses nicht wichtig ist, können Sie auf alle Ereignisse warten, Änderungen in einem Cloud Firestore-Dokument mit dem Text „Dokument geschrieben“ Termin auslösen. Diese Beispielfunktion wird ausgelöst, wenn ein Nutzer erstellt, aktualisiert oder gelöscht wird:
Node.js
import {
onDocumentWritten,
Change,
FirestoreEvent
} from "firebase-functions/v2/firestore";
exports.modifyuser = onDocumentWritten("users/{userId}", (event) => {
// Get an object with the current document values.
// If the document does not exist, it was deleted
const document = event.data.after.data();
// Get an object with the previous document values
const previousValues = event.data.before.data();
// perform more operations ...
});
Wenn Sie zusätzliche Informationen zur Authentifizierung benötigen, verwenden Sie onDocumentWrittenWithAuthContext
.
Python (Vorabversion)
from firebase_functions.firestore_fn import (
on_document_written,
Event,
Change,
DocumentSnapshot,
)
@on_document_written(document="users/{userId}")
def myfunction(event: Event[Change[DocumentSnapshot | None]]) -> None:
# Get an object with the current document values.
# If the document does not exist, it was deleted.
document = (event.data.after.to_dict()
if event.data.after is not None else None)
# Get an object with the previous document values.
# If the document does not exist, it was newly created.
previous_values = (event.data.before.to_dict()
if event.data.before is not None else None)
# Perform more operations ...
Daten lesen und schreiben
Wenn eine Funktion ausgelöst wird, stellt sie einen Snapshot der Daten bereit, die sich auf das Ereignis beziehen. Sie können diesen Snapshot verwenden, um das Dokument zu lesen oder zu schreiben, das das Ereignis ausgelöst hat, oder das Firebase Admin SDK verwenden, um auf andere Teile Ihrer Datenbank zuzugreifen.
Ereignisdaten
Daten lesen
Wenn eine Funktion ausgelöst wird, möchten Sie möglicherweise Daten aus einem Dokument abrufen, das aktualisiert wurde, oder die Daten vor der Aktualisierung abrufen. Sie können die vorherigen Daten mithilfe von event.data.before
abrufen, das den Dokument-Snapshot vor der Aktualisierung enthält.
Entsprechend enthält event.data.after
den Status des Dokument-Snapshots nach der Aktualisierung.
Node.js
exports.updateuser2 = onDocumentUpdated("users/{userId}", (event) => {
// Get an object with the current document values.
// If the document does not exist, it was deleted
const newValues = event.data.after.data();
// Get an object with the previous document values
const previousValues = event.data.before.data();
});
Python (Vorabversion)
@on_document_updated(document="users/{userId}")
def myfunction(event: Event[Change[DocumentSnapshot]]) -> None:
# Get an object with the current document values.
new_value = event.data.after.to_dict()
# Get an object with the previous document values.
prev_value = event.data.before.to_dict()
Sie können auf Attribute wie in jedem anderen Objekt zugreifen. Alternativ können Sie die Funktion get
für den Zugriff auf bestimmte Felder verwenden:
Node.js
// Fetch data using standard accessors
const age = event.data.after.data().age;
const name = event.data.after.data()['name'];
// Fetch data using built in accessor
const experience = event.data.after.data.get('experience');
Python (Vorabversion)
# Get the value of a single document field.
age = event.data.after.get("age")
# Convert the document to a dictionary.
age = event.data.after.to_dict()["age"]
Daten schreiben
Jeder Funktionsaufruf ist mit einem bestimmten Dokument in Ihrem Cloud Firestore-Datenbank. Sie können auf dieses Dokument zugreifen in den an Ihre Funktion zurückgegebenen Snapshot.
Die Dokumentreferenz enthält Methoden wie update()
, set()
und remove()
sodass Sie das Dokument ändern können, das die Funktion ausgelöst hat.
Node.js
import { onDocumentUpdated } from "firebase-functions/v2/firestore";
exports.countnamechanges = onDocumentUpdated('users/{userId}', (event) => {
// Retrieve the current and previous value
const data = event.data.after.data();
const previousData = event.data.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 data.after.ref.set({
name_change_count: count + 1
}, {merge: true});
});
Python (Vorabversion)
@on_document_updated(document="users/{userId}")
def myfunction(event: Event[Change[DocumentSnapshot]]) -> None:
# Get the current and previous document values.
new_value = event.data.after
prev_value = event.data.before
# We'll only update if the name has changed.
# This is crucial to prevent infinite loops.
if new_value.get("name") == prev_value.get("name"):
return
# Retrieve the current count of name changes
count = new_value.to_dict().get("name_change_count", 0)
# Update the count
new_value.reference.update({"name_change_count": count + 1})
Auf Informationen zur Nutzerauthentifizierung zugreifen
Wenn Sie einen der folgenden Ereignistypen verwenden, können Sie auf Informationen zur Nutzerauthentifizierung des Principals zugreifen, der das Ereignis ausgelöst hat. Diese Informationen ergänzen die im Basisereignis zurückgegebenen Informationen.
Node.js
onDocumentCreatedWithAuthContext
onDocumentWrittenWithAuthContext
onDocumentDeletedWithAuthContext
onDocumentUpdatedWithAuthContext
Python (Vorabversion)
on_document_created_with_auth_context
on_document_updated_with_auth_context
on_document_deleted_with_auth_context
on_document_written_with_auth_context
Informationen zu den im Authentifizierungskontext verfügbaren Daten finden Sie unter Auth-Kontext: Das folgende Beispiel zeigt, wie Authentifizierungsinformationen abgerufen werden:
Node.js
import { onDocumentWrittenWithAuthContext } from "firebase-functions/v2/firestore"
exports.syncUser = onDocumentWrittenWithAuthContext("users/{userId}", (event) => {
const snapshot = event.data.after;
if (!snapshot) {
console.log("No data associated with the event");
return;
}
const data = snapshot.data();
// retrieve auth context from event
const { authType, authId } = event;
let verified = false;
if (authType === "system") {
// system-generated users are automatically verified
verified = true;
} else if (authType === "unknown" || authType === "unauthenticated") {
// admin users from a specific domain are verified
if (authId.endsWith("@example.com")) {
verified = true;
}
}
return data.after.ref.set({
created_by: authId,
verified,
}, {merge: true});
});
Python (Vorabversion)
@on_document_updated_with_auth_context(document="users/{userId}")
def myfunction(event: Event[Change[DocumentSnapshot]]) -> None:
# Get the current and previous document values.
new_value = event.data.after
prev_value = event.data.before
# Get the auth context from the event
user_auth_type = event.auth_type
user_auth_id = event.auth_id
Daten außerhalb des Triggerereignisses
Cloud Functions werden in einer vertrauenswürdigen Umgebung ausgeführt. Es ist als Dienstkonto in Ihrem Projekt autorisiert und Sie können Lese- und Schreibvorgänge mit dem Firebase Admin SDK ausführen:
Node.js
const { initializeApp } = require('firebase-admin/app');
const { getFirestore, Timestamp, FieldValue } = require('firebase-admin/firestore');
initializeApp();
const db = getFirestore();
exports.writetofirestore = onDocumentWritten("some/doc", (event) => {
db.doc('some/otherdoc').set({ ... });
});
exports.writetofirestore = onDocumentWritten('users/{userId}', (event) => {
db.doc('some/otherdoc').set({
// Update otherdoc
});
});
Python (Vorabversion)
from firebase_admin import firestore, initialize_app
import google.cloud.firestore
initialize_app()
@on_document_written(document="some/doc")
def myfunction(event: Event[Change[DocumentSnapshot | None]]) -> None:
firestore_client: google.cloud.firestore.Client = firestore.client()
firestore_client.document("another/doc").set({
# ...
})
Beschränkungen
Beachten Sie die folgenden Einschränkungen für Cloud Firestore-Trigger für Cloud Functions:
- Für Cloud Functions (1. Generation) muss ein vorhandener „(Standard)“ vorhanden sein im nativen Modus von Firestore verwenden. Nicht unterstützen Cloud Firestore-benannte Datenbanken oder den Datastore-Modus. Bitte Cloud Functions verwenden (2. Generation), um in solchen Fällen Ereignisse zu konfigurieren.
- Die Reihenfolge ist nicht garantiert. Schnelle Änderungen können Funktionsaufrufe in einer unvorhergesehenen Reihenfolge auslösen.
- Ereignisse werden mindestens einmal übergeben. Ein einzelnes Ereignis kann aber zu mehreren Funktionsaufrufen führen. Vermeiden Sie die Abhängigkeit von genau einmal vorkommenden Verfahren und schreiben Sie idempotente Funktionen.
- Cloud Firestore im Datastore-Modus erfordert Cloud Functions (2. Generation). Cloud Functions (1. Generation) nicht unterstützen den Datastore-Modus.
- Ein Trigger ist einer einzelnen Datenbank zugeordnet. Sie können keinen Trigger erstellen, der mit mehreren Datenbanken übereinstimmt.
- Durch das Löschen einer Datenbank werden nicht automatisch die Trigger für diese Datenbank gelöscht. Die Der Trigger liefert keine Ereignisse mehr. Er bleibt jedoch bestehen, bis Sie den Trigger löschen.
- Überschreitet ein übereinstimmendes Ereignis die maximale Anfragegröße, wird das Ereignis
wird möglicherweise nicht an Cloud Functions (1. Generation) gesendet.
- Ereignisse, die aufgrund der Größe der Anfrage nicht zugestellt wurden, werden in Plattformlogs protokolliert und auf die Lognutzung für das Projekt angerechnet.
- Sie finden diese Logs im Log-Explorer mit der Meldung "Ereignis kann nicht an die Cloud Functions-Funktion gesendet werden, da die Größe das Limit für die 1. Generation überschreitet..." mit dem Schweregrad
error
. Sie finden den Funktionsnamen unter dem FeldfunctionName
. Wenn Das FeldreceiveTimestamp
befindet sich immer noch in einer Stunde, können Sie ableiten, des Veranstaltungsinhalts ansehen, indem Sie das entsprechende Dokument mit einem Snapshot vor und nach dem Zeitstempel. - So kannst du einen solchen Ablauf vermeiden:
- Migrieren und zu Cloud Functions (2. Generation) migrieren
- Dokument verkleinern
- Betreffende Cloud Functions löschen
- Sie können das Logging selbst mithilfe von Ausschlüssen deaktivieren. Beachten Sie jedoch, dass die betreffenden Ereignisse dennoch nicht übermittelt werden.