С помощью Cloud Functions вы можете развертывать код для обработки событий, запускаемых изменениями в вашей базе данных Cloud Firestore, совместимой с MongoDB. Это позволяет добавлять функциональность на стороне сервера в ваше приложение без необходимости запуска собственных серверов.
Cloud Functions (2-го поколения)
Cloud Functions for Firebase (2nd gen), работающая на базе Cloud Run и Eventarc , предоставляет более мощную инфраструктуру, расширенный контроль над производительностью и масштабируемостью, а также больший контроль над средой выполнения функций. Для получения дополнительной информации о 2nd gen см. Cloud Functions for Firebase (2nd gen) .
Функция запуска триггеров в Cloud Firestore с совместимостью с MongoDB
SDK Cloud Functions for Firebase экспортирует следующие триггеры событий совместимости с Cloud Firestore и MongoDB, позволяя создавать обработчики, привязанные к конкретным событиям совместимости с Cloud Firestore и MongoDB:
Node.js
| Тип события | Курок |
|---|---|
onDocumentCreated | Срабатывает при первой записи в документ. |
onDocumentUpdated | Срабатывает, когда документ уже существует и в нем изменено какое-либо значение. |
onDocumentDeleted | Срабатывает при удалении документа. |
onDocumentWritten | Срабатывает при срабатывании событий onDocumentCreated , onDocumentUpdated или onDocumentDeleted . |
onDocumentCreatedWithAuthContext | onDocumentCreated with additional authentication information |
onDocumentWrittenWithAuthContext | onDocumentWritten с дополнительной информацией для аутентификации |
onDocumentDeletedWithAuthContext | onDocumentDeleted с дополнительной информацией для аутентификации |
onDocumentUpdatedWithAuthContext | onDocumentUpdated с дополнительной информацией об аутентификации |
Python
| Тип события | Курок |
|---|---|
on_document_created | Срабатывает при первой записи в документ. |
on_document_updated | Срабатывает, когда документ уже существует и в нем изменено какое-либо значение. |
on_document_deleted | Срабатывает при удалении документа. |
on_document_written | Срабатывает при срабатывании событий on_document_created , on_document_updated или on_document_deleted . |
on_document_created_with_auth_context | on_document_created с дополнительной информацией для аутентификации |
on_document_updated_with_auth_context | on_document_updated с дополнительной информацией для аутентификации |
on_document_deleted_with_auth_context | on_document_deleted с дополнительной информацией для аутентификации |
on_document_written_with_auth_context | on_document_written с дополнительной информацией для аутентификации |
События совместимости Cloud Firestore с MongoDB срабатывают только при изменении документа. Обновление документа, совместимого с Cloud Firestore с MongoDB, в котором данные остаются неизменными (запись без изменений), не генерирует событие обновления или записи. Добавить события к конкретным полям невозможно.
Если у вас еще нет проекта, поддерживающего Cloud Functions for Firebase , прочтите руководство «Начало работы с Cloud Functions for Firebase (2-го поколения)», чтобы настроить и подготовить свой проект Cloud Functions for Firebase .
Разработка Cloud Firestore с функциями, запускаемыми при совместимости с MongoDB.
Определите триггер функции
Для определения триггера Cloud Firestore, совместимого с MongoDB, укажите путь к документу и тип события:
Node.js
const {
onDocumentWritten,
onDocumentCreated,
onDocumentUpdated,
onDocumentDeleted,
Change,
FirestoreEvent
} = require('firebase-functions/v2/firestore');
exports.myfunction = onDocumentWritten("my-collection/{docId}", (event) => {
/* ... */
});
Python
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:
Пути к документам могут ссылаться либо на конкретный документ , либо на шаблон с подстановочным знаком .
Укажите один документ
Если вы хотите инициировать событие при любом изменении в конкретном документе, вы можете использовать следующую функцию.
Node.js
const {
onDocumentWritten,
Change,
FirestoreEvent
} = require('firebase-functions/v2/firestore');
exports.myfunction = onDocumentWritten("users/marie", (event) => {
// Your code here
});
Python
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:
Укажите группу документов, используя символы подстановки.
Если вы хотите привязать триггер к группе документов, например, к любому документу в определенной коллекции, используйте символ {wildcard} вместо идентификатора документа:
Node.js
const {
onDocumentWritten,
Change,
FirestoreEvent
} = require('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
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
В этом примере при изменении любого поля в любом документе в базе данных users используется подстановочный знак userId .
Сопоставление с использованием подстановочных символов извлекается из пути к документу и сохраняется в файле event.params . Ваш триггер всегда должен указывать на документ, даже если вы используете подстановочный символ.
Триггеры событий
Запустить функцию при создании нового документа
Вы можете настроить функцию таким образом, чтобы она срабатывала каждый раз при создании нового документа в коллекции. В этом примере функция срабатывает каждый раз при добавлении нового профиля пользователя:
Node.js
const {
onDocumentCreated,
Change,
FirestoreEvent
} = require('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 ...
});
Для получения дополнительной информации об аутентификации используйте onDocumentCreatedWithAuthContext .
Python
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 ...
Запустить функцию при обновлении документа
Вы также можете инициировать выполнение функции при обновлении документа. В этом примере функция срабатывает, если пользователь изменяет свой профиль:
Node.js
const {
onDocumentUpdated,
Change,
FirestoreEvent
} = require('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 ...
});
Для получения дополнительной информации об аутентификации используйте onDocumentUpdatedWithAuthContext .
Python
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 ...
Запустить функцию при удалении документа
Вы также можете запустить функцию при удалении документа. В этом примере функция срабатывает, когда пользователь удаляет свой профиль:
Node.js
const {
onDocumentDeleted,
Change,
FirestoreEvent
} = require('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 ...
});
Для получения дополнительной информации об аутентификации используйте onDocumentDeletedWithAuthContext .
Python
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 ...
Запустить функцию для всех изменений в документе.
Если вас не интересует тип генерируемого события, вы можете отслеживать все изменения в документе, совместимом с Cloud Firestore и MongoDB, используя триггер события "document written". В этом примере функция срабатывает при создании, обновлении или удалении пользователя:
Node.js
const {
onDocumentWritten,
Change,
FirestoreEvent
} = require('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 ...
});
Для получения дополнительной информации об аутентификации используйте onDocumentWrittenWithAuthContext .
Python
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 ...
Чтение и запись данных
При срабатывании функции создается снимок данных, связанных с событием. Вы можете использовать этот снимок для чтения или записи в документ, вызвавший событие, или использовать Firebase Admin SDK для доступа к другим частям вашей базы данных.
Данные события
Чтение данных
Когда срабатывает функция, вам может потребоваться получить данные из обновленного документа или данные, существовавшие до обновления. Предварительные данные можно получить с помощью event.data.before , который содержит снимок состояния документа до обновления. Аналогично, event.data.after содержит снимок состояния документа после обновления.
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
@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()
Вы можете получать доступ к свойствам так же, как и к любому другому объекту. В качестве альтернативы, вы можете использовать функцию get для доступа к конкретным полям:
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
# 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"]
Запись данных
Каждый вызов функции связан с конкретным документом в вашей базе данных Cloud Firestore, совместимой с MongoDB. Вы можете получить доступ к этому документу в снимке, возвращаемом вашей функцией.
В справочнике документов указаны такие методы, как update() , set() и remove() , позволяющие изменять документ, вызвавший данную функцию.
Node.js
const {onDocumentUpdated} = require('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 event.data.after.ref.set({
name_change_count: count + 1
}, {merge: true});
});
Python
@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})
Доступ к информации для аутентификации пользователя
При использовании одного из следующих типов событий вы можете получить доступ к информации об аутентификации пользователя, инициировавшего событие. Эта информация предоставляется в дополнение к информации, возвращаемой в базовом событии.
Node.js
-
onDocumentCreatedWithAuthContext -
onDocumentWrittenWithAuthContext -
onDocumentDeletedWithAuthContext -
onDocumentUpdatedWithAuthContext
Python
-
on_document_created_with_auth_context -
on_document_updated_with_auth_context -
on_document_deleted_with_auth_context -
on_document_written_with_auth_context
Для получения информации о данных, доступных в контексте аутентификации, см. раздел «Контекст аутентификации» . Следующий пример демонстрирует, как получить информацию об аутентификации:
Node.js
const {onDocumentWrittenWithAuthContext} = require('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
@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
Данные вне событий запуска
Cloud Functions выполняются в доверенной среде. Они авторизованы как сервисные учетные записи в вашем проекте, и вы можете выполнять операции чтения и записи с помощью Firebase Admin SDK .
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
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({
# ...
})
Ограничения
- Порядок выполнения не гарантируется. Быстрые изменения могут привести к вызову функций в неожиданном порядке.
- События доставляются как минимум один раз, но одно событие может привести к нескольким вызовам функций. Избегайте зависимости от механизма "точно один раз" и пишите идемпотентные функции .
- Триггер связан с одной конкретной базой данных. Нельзя создать триггер, который бы соответствовал нескольким базам данных.
- Удаление базы данных не приводит к автоматическому удалению всех триггеров для этой базы данных. Триггер перестает генерировать события, но продолжает существовать до тех пор, пока вы его не удалите .