С помощью облачных функций вы можете обрабатывать события в Cloud Firestore без необходимости обновлять клиентский код. Вы можете вносить изменения в Cloud Firestore через интерфейс моментального снимка документа или через Admin SDK .
В типичном жизненном цикле функция Cloud Firestore выполняет следующие действия:
- Ожидает изменений в конкретном документе.
- Запускается при возникновении события и выполняет свои задачи.
- Получает объект данных, содержащий моментальный снимок данных, хранящихся в указанном документе. Для событий записи или обновления объект данных содержит два моментальных снимка, которые представляют состояние данных до и после инициирующего события.
Расстояние между расположением экземпляра Firestore и расположением функции может привести к значительной задержке в сети. Чтобы оптимизировать производительность, рассмотрите возможность указания местоположения функции , где это применимо.
Триггеры функции Cloud Firestore
Cloud Functions для Firebase SDK экспортирует объект functions.firestore
, который позволяет создавать обработчики, привязанные к определенным событиям Cloud Firestore.
Тип события | Курок |
---|---|
onCreate | Запускается, когда документ записывается в первый раз. |
onUpdate | Запускается, когда документ уже существует и любое значение изменено. |
onDelete | Срабатывает при удалении документа с данными. |
onWrite | Запускается, когда запускается onCreate , onUpdate или onDelete . |
Если у вас еще нет проекта с включенными облачными функциями для Firebase, прочтите статью Начало работы: напишите и разверните свои первые функции , чтобы настроить и настроить проект облачных функций для Firebase.
Написание функций, запускаемых Cloud Firestore
Определить триггер функции
Чтобы определить триггер Cloud Firestore, укажите путь к документу и тип события:
Node.js
const functions = require('firebase-functions');
exports.myFunction = functions.firestore
.document('my-collection/{docId}')
.onWrite((change, context) => { /* ... */ });
Пути к документам могут ссылаться либо на конкретный документ , либо на подстановочный знак .
Укажите один документ
Если вы хотите инициировать событие для любого изменения в конкретном документе, вы можете использовать следующую функцию.
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 });
Укажите группу документов с помощью подстановочных знаков
Если вы хотите прикрепить триггер к группе документов, например к любому документу в определенной коллекции, используйте {wildcard}
вместо идентификатора документа:
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"} });
В этом примере при изменении любого поля в любом документе users
оно соответствует подстановочному знаку с именем userId
.
Если документ users
имеет вложенные коллекции, а поле в одном из документов этих вложенных коллекций изменено, подстановочный знак userId
не срабатывает.
Совпадения с подстановочными знаками извлекаются из пути к документу и сохраняются в context.params
. Вы можете определить любое количество подстановочных знаков для замены явных идентификаторов коллекций или документов, например:
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"} });
Триггеры событий
Запуск функции при создании нового документа
Вы можете запускать функцию каждый раз, когда в коллекции создается новый документ, используя обработчик onCreate()
с подстановочным знаком . В этом примере функция вызывает createUser
каждый раз, когда добавляется новый профиль пользователя:
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 ... });
Запуск функции при обновлении документа
Вы также можете вызвать функцию для запуска при обновлении документа с помощью функции onUpdate()
с подстановочным знаком . В этом примере функция вызывает updateUser
если пользователь меняет свой профиль:
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 ... });
Активировать функцию при удалении документа
Вы также можете вызвать функцию при удалении документа, используя функцию onDelete()
с подстановочным знаком . В этом примере функция вызывает deleteUser
, когда пользователь удаляет свой профиль:
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 ... });
Активировать функцию для всех изменений в документе
Если вас не волнует тип запускаемого события, вы можете прослушивать все изменения в документе Cloud Firestore, используя функцию onWrite()
с подстановочным знаком . В этом примере функция вызывает modifyUser
если пользователь создан, обновлен или удален:
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 ... });
Чтение и запись данных
Когда функция запускается, она предоставляет моментальный снимок данных, связанных с событием. Вы можете использовать этот снимок для чтения или записи в документ, вызвавший событие, или использовать Firebase Admin SDK для доступа к другим частям вашей базы данных.
Данные события
Чтение данных
При запуске функции может потребоваться получить данные из документа, который был обновлен, или получить данные до обновления. Вы можете получить предыдущие данные, используя change.before.data()
, который содержит снимок документа до обновления. Точно так же change.after.data()
содержит состояние моментального снимка документа после обновления.
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(); });
Вы можете получить доступ к свойствам, как и к любому другому объекту. Кроме того, вы можете использовать функцию get
для доступа к определенным полям:
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');
Запись данных
Каждый вызов функции связан с определенным документом в вашей базе данных Cloud Firestore. Вы можете получить доступ к этому документу как DocumentReference
в свойстве ref
моментального снимка, возвращаемого вашей функцией.
Этот DocumentReference
поступает из SDK Cloud Firestore Node.js и включает такие методы, как update()
, set()
и remove()
, поэтому вы можете легко изменить документ, вызвавший функцию.
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}); });
Данные вне триггерного события
Облачные функции выполняются в доверенной среде, что означает, что они авторизованы как учетная запись службы в вашем проекте. Вы можете выполнять чтение и запись с помощью 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({ ... });
});
Ограничения
Обратите внимание на следующие ограничения для триггеров Cloud Firestore для облачных функций:
- Заказ не гарантируется. Быстрые изменения могут инициировать вызовы функций в неожиданном порядке.
- События доставляются по крайней мере один раз, но одно событие может привести к вызову нескольких функций. Избегайте зависимости от однократной механики и пишите идемпотентные функции .
- Триггеры Cloud Firestore для Cloud Functions доступны только для Cloud Firestore в собственном режиме . Он недоступен для Cloud Firestore в режиме хранилища данных.