Com Cloud Functions, é possível implantar o código para processar eventos acionados por mudanças no banco de dados do Cloud Firestore com compatibilidade com o MongoDB. Isso permite adicionar funcionalidade do lado do servidor ao seu app sem executar seus próprios servidores.
Cloud Functions (2ª geração)
Tecnologia do Cloud Run e Eventarc, O Cloud Functions for Firebase (2a geração) oferece recursos mais avançados infraestrutura, controle avançado sobre o desempenho e a escalonabilidade, e muito mais do ambiente de execução das funções. Para mais informações sobre a segunda geração, consulte Cloud Functions para Firebase (2ª geração).
Gatilhos de função do Cloud Firestore com compatibilidade com o MongoDB
O SDK do Cloud Functions for Firebase exporta os seguintes gatilhos de evento do Cloud Firestore com compatibilidade com o MongoDB para permitir que você crie gerenciadores relacionados a eventos específicos do Cloud Firestore com compatibilidade com o MongoDB:
Node.js
| Tipo de evento | Gatilho |
|---|---|
onDocumentCreated |
Acionado quando um documento é gravado pela primeira vez. |
onDocumentUpdated |
Acionado quando um documento já existe e tem algum valor alterado. |
onDocumentDeleted |
Acionado quando um documento é excluído. |
onDocumentWritten |
Acionado quando onDocumentCreated, onDocumentUpdated ou onDocumentDeleted é acionado. |
onDocumentCreatedWithAuthContext |
onDocumentCreated com mais informações de autenticação |
onDocumentWrittenWithAuthContext |
onDocumentWritten com mais informações de autenticação |
onDocumentDeletedWithAuthContext |
onDocumentDeleted com mais informações de autenticação |
onDocumentUpdatedWithAuthContext |
onDocumentUpdated com mais informações de autenticação |
Python
| Tipo de evento | Gatilho |
|---|---|
on_document_created |
Acionado quando um documento é gravado pela primeira vez. |
on_document_updated |
Acionado quando um documento já existe e tem algum valor alterado. |
on_document_deleted |
Acionado quando um documento é excluído. |
on_document_written |
Acionado quando on_document_created, on_document_updated ou on_document_deleted é acionado. |
on_document_created_with_auth_context |
on_document_created com mais informações de autenticação |
on_document_updated_with_auth_context |
on_document_updated com mais informações de autenticação |
on_document_deleted_with_auth_context |
on_document_deleted com mais informações de autenticação |
on_document_written_with_auth_context |
on_document_written com mais informações de autenticação |
Os eventos do Cloud Firestore com compatibilidade com o MongoDB são acionados somente se houver mudanças nos documentos. Uma atualização em um documento do Cloud Firestore com compatibilidade com o MongoDB, em que os dados permanecem inalterados (uma gravação em ambiente autônomo), não vai gerar um evento de atualização ou gravação. Não é possível adicionar eventos a campos específicos.
Se você ainda não ativou um projeto para Cloud Functions for Firebase, leia Começar a usar o Cloud Functions for Firebase (2a geração) para configurar seu projeto do Cloud Functions for Firebase.
Como escrever funções acionadas pelo Cloud Firestore com compatibilidade com o MongoDB
Definir um gatilho de função
Para definir um gatilho do Cloud Firestore com compatibilidade com o MongoDB, especifique um caminho do documento e um tipo de evento:
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:
Os caminhos do documento podem se referir a um documento específico ou a um padrão de caracteres curinga.
Especificar um único documento
Se você quiser acionar um evento para qualquer alteração em um documento específico, use a seguinte função.
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:
Especificar um grupo de documentos com caracteres curinga
Para adicionar um gatilho a um grupo de documentos, como qualquer documento em
uma determinada coleção, use um {wildcard} no lugar do
ID do documento:
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
Neste exemplo, quando qualquer campo em qualquer documento em users é alterado, ele corresponde
a um caractere curinga chamado userId.
As correspondências de caracteres curinga são extraídas do caminho do documento e armazenadas em event.params.
É preciso que seu gatilho aponte sempre para um documento, mesmo que você esteja usando um caractere curinga.
Gatilhos de eventos
Acionar uma função quando um novo documento é criado
Você pode acionar uma função sempre que um novo documento for criado em uma coleção. Este exemplo de função é acionado sempre que um novo perfil de usuário é adicionado:
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 ...
});
Para mais informações de autenticação, use 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 ...
Acionar uma função quando um documento é atualizado
Você também pode acionar uma função quando um documento for atualizado. Esta função de exemplo é acionada quando um perfil de usuário for alterado:
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 ...
});
Para mais informações de autenticação, use 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 ...
Acionar uma função quando um documento é excluído
Também é possível acionar uma função quando um documento for excluído. Esta função de exemplo é acionada quando um perfil de usuário for excluído:
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 ...
});
Para mais informações de autenticação, use 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 ...
Acionar uma função para todas as alterações em um documento
Se o tipo de evento acionado não for relevante, será possível detectar todas as alterações em um documento do Cloud Firestore com compatibilidade com o MongoDB usando o acionador de evento "documento gravado". Esta função de exemplo é acionada se um usuário for criado, atualizado ou excluído:
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 ...
});
Para mais informações de autenticação, use 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 ...
Como ler e gravar dados
Quando uma função é acionada, ela fornece um snapshot dos dados relacionados ao evento. É possível usar esse snapshot para ler ou gravar no documento usado para acionar o evento ou usar o SDK Admin do Firebase para acessar outras partes do seu banco de dados.
Dados de eventos
Como ler dados
Quando uma função é acionada, é possível que você queira ver os dados de um documento antes ou depois de que ele seja atualizado. Para conseguir os dados anteriores, basta usar
event.data.before, que contém o snapshot do documento antes da atualização.
Da mesma forma, event.data.after contém o estado do snapshot do documento após a atualização.
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()
Acesse as propriedades como faria em qualquer outro objeto. Como alternativa,
use a função get para acessar campos específicos:
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"]
Como gravar dados
Cada invocação de função está associada a um documento específico no seu banco de dados do Cloud Firestore com compatibilidade com o MongoDB. É possível acessar esse documento no snapshot retornado para sua função.
A referência do documento inclui métodos como update(), set() e remove()
para que você possa modificar o documento que acionou a função.
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})
Acessar informações de autenticação do usuário
Se você usar um dos tipos de evento a seguir, poderá acessar informações de autenticação do usuário sobre o principal que acionou o evento. Essas informações são adicionadas às informações retornadas no evento base.
Node.js
onDocumentCreatedWithAuthContextonDocumentWrittenWithAuthContextonDocumentDeletedWithAuthContextonDocumentUpdatedWithAuthContext
Python
on_document_created_with_auth_contexton_document_updated_with_auth_contexton_document_deleted_with_auth_contexton_document_written_with_auth_context
Para mais informações sobre os dados disponíveis no contexto de autenticação, consulte Contexto da autenticação. O exemplo a seguir demonstra como recuperar informações de autenticação:
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
Dados fora do evento acionador
Cloud Functions são executados em um ambiente confiável. Os dados são autorizados como uma conta de serviço no projeto, e é possível executar leituras e gravações usando o SDK Admin do Firebase:
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({
# ...
})
Limitações
- Não garantimos acionamentos em ordem. Alterações rápidas podem acionar invocações de função em uma ordem inesperada.
- Os eventos são entregues pelo menos uma vez, mas um único evento pode resultar em invocações de várias funções. Evite depender de mecanismos do tipo "apenas uma vez" e escreva funções idempotentes.
- Um gatilho está associado a um único banco de dados. Não é possível criar um gatilho que corresponda a vários bancos de dados.
- A exclusão de um banco de dados não remove automaticamente nenhum gatilho dele. O acionador deixa de entregar eventos, mas continua existindo até que você o exclua.