Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

Melhores práticas e um tutorial para usar o Google Cloud Functions com o MongoDB Atlas

13 min read • Published Apr 18, 2023 • Updated Jun 13, 2023
Google cloudAtlas
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Os aplicativos sem servidor estão se tornando cada vez mais populares entre os desenvolvedores. Eles oferecem uma maneira econômica e eficiente de lidar com a lógica de aplicativos e o armazenamento de dados. Duas das tecnologias mais populares que podem ser usadas em conjunto para criar aplicativos sem servidor são o Google Cloud Functions e o MongoDB Atlas.
Com o Google Cloud Functions, os desenvolvedores executam seu código em resposta a eventos, como alterações em dados ou solicitações HTTP, sem precisar gerenciar a infraestrutura subjacente. Isso facilita a criação de aplicativos escaláveis e de alto desempenho. O MongoDB Atlas, por outro lado, fornece uma plataforma de dados totalmente gerenciada, distribuída globalmente e altamente disponível. Isso torna mais fácil para os desenvolvedores armazenar e gerenciar seus dados de maneira confiável e segura.
Neste artigo, discutiremos três práticas recomendadas para trabalhar com bancos de dados no Google Cloud Functions. Primeiro, exploraremos os benefícios de abrir conexões de banco de dados no escopo global. Em seguida, abordaremos como tornar suas operações de banco de dados idempotentes para garantir a consistência dos dados em funções orientadas a eventos. Por fim, discutiremos como configurar uma conexão de rede segura para proteger seus dados contra acesso não autorizado. Seguindo essas melhores práticas, você pode criar funções orientadas por eventos mais confiáveis e seguras que funcionem perfeitamente com seus bancos de dados.

Pré-requisitos

Os requisitos mínimos para seguir este tutorial são:
  • Um banco de dadosdo MongoDB Atlas com um usuário de banco de dados e uma configuração de rede apropriada.
  • Uma conta do Google Cloud com faturamento ativado.
  • Cloud Functions, Cloud Build, Registro de artefatos, Cloud Run, Logging e APIs Pub/Sub ativados. Siga este link para habilitar as APIs necessárias.
Você mesmo pode fazer as experiências mostradas neste artigo. Tanto o MongoDB Atlas quanto o Cloud Functions oferecem uma camada gratuita suficiente para os dois primeiros exemplos. O exemplo final - configurar uma rede VPC ou Private Service Connect - requer a configuração de um banco de dados Atlas pago e dedicado e o uso de recursos pagos do Google Cloud.

Conexões de banco de dados abertas no escopo global

Digamos que estamos criando um aplicativo tradicional auto-hospedado que se conecta ao MongoDB. Podemos abrir uma nova conexão toda vez que precisarmos nos comunicar com o banco de dados e, em seguida, fechar imediatamente essa conexão. Mas a abertura e o fechamento de conexões adiciona uma sobrecarga tanto ao servidor do banco de dados quanto ao nosso aplicativo. É muito mais eficiente reutilizar a mesma conexão toda vez que enviamos uma solicitação ao banco de dados. Normalmente, nos conectamos ao banco de dados usando um driver MongoDB quando iniciamos o aplicativo, salvamos a conexão em uma variável globalmente acessível e a usamos para enviar solicitações. Enquanto o aplicativo estiver em execução, a conexão permanecerá aberta.
Para ser mais preciso, quando nos conectamos, o driver MongoDB cria um pool de conexões. Isso permite que solicitações simultâneas se comuniquem com o banco de dados. O driver gerenciará automaticamente as conexões no pool, criando novas quando necessárias e fechando-as quando estiverem ociosas. O pool também limita o número de conexões que podem vir de uma única instância do aplicativo (100 conexões é o padrão).
Pool de conexões
Por outro lado, as funções do Cloud são sem servidor. Eles são muito eficientes em aumentar automaticamente quando várias solicitações simultâneas chegam e diminuir quando a demanda diminui.
Por padrão, cada instância de função pode lidar com apenas uma solicitação por vez. No entanto, com oCloud Functions 2nd geração, você pode configurar suas funções para lidar com solicitações simultâneas. Por exemplo, se você definir o parâmetro de simultaneidade como 10, uma única instância de função poderá trabalhar em um máximo de 10 solicitações ao mesmo tempo. Se formos cuidadosos com a forma como nos conectamos ao banco de dados, as solicitações aproveitarão o pool de conexões criado pelo driver MongoDB. Nesta seção, exploraremos estratégias específicas para reutilizar conexões.
Por padrão, o Cloud Functions pode girar até 1,000 novas instâncias. No entanto, cada instância de função é executada em seu próprio contexto de execução isolado. Isso significa que as instâncias não podem compartilhar um pool de conexões de banco de dados. É por isso que precisamos prestar atenção à maneira como abrimos as conexões do banco de dados. Se tivermos nosso parâmetro de simultaneidade definido como 1 e abrirmos uma nova conexão com cada solicitação, causaremos sobrecarga desnecessária no banco de dados ou até atingiremos o limite máximo de conexões.
Conexões de funções da nuvem
Isso parece muito ineficiente! Felizmente, há uma maneira melhor de fazer isso. Podemos aproveitar a maneira como o Cloud Functions reutiliza instâncias já iniciadas.
Mencionamos anteriormente que o Cloud Functions é dimensionado ativando novas instâncias para lidar com solicitações recebidas. A criação de uma instância totalmente nova é chamada de “cold start” e envolve as seguintes etapas:
  1. Carregando o ambiente de tempo de execução.
  2. Executar o escopo global (em toda a instância) da função.
  3. Executando o corpo da função definido como um "entry point. "
Quando a instância lida com a solicitação, ela não é fechada imediatamente. Se recebermos outra solicitação nos próximos minutos, as chances são altas de que ela seja roteada para a mesma instância, já "warmed". Mas desta vez, somente a função "entry point " será invocada. E o mais importante é que a função será invocada no mesmo ambiente de execução. Na prática, isso significa que tudo o que definimos no escopo global pode ser reutilizado - incluindo uma conexão com o banco de dados! Isso reduzirá a sobrecarga de abrir uma nova conexão com cada invocação de função.
Embora possamos aproveitar o escopo global para armazenar uma conexão reutilizável, não há garantia de que uma conexão reutilizável será usada.
Vamos testar essa teoria! Faremos o seguinte experimento:
  1. Criaremos duas funções do Cloud que inserem um documento em um banco de dados do MongoDB Atlas. Também anexaremos um ouvinte de eventos que registra uma mensagem sempre que uma nova conexão de banco de dados for criada.
    1. A primeira função se conectará ao Atlas no escopo da função.
    2. A segunda função se conectará ao Atlas no escopo global.
  2. Enviaremos solicitações simultâneas 50 para cada função e esperaremos que elas sejam concluídas. Em teoria, depois de ativar algumas instâncias, o Cloud Functions as reutilizará para lidar com algumas das solicitações.
  3. Por fim, inspecionaremos os registros para ver quantas conexões de banco de dados foram criadas em cada caso.
Antes de iniciar, volte ao seu Atlas e localize sua connection string. Além disso, certifique-se de permitir o acesso de qualquer lugar nas configurações de rede. Em vez disso, é altamente recomendável estabelecer uma conexão segura.

Criar a função do Cloud com conexão de banco de dados com escopo de função

Usaremos o console do Google Cloud para realizar nosso experimento. Navegue até a páginaFunções da nuvem e certifique-se de fazer login, selecionar um projeto e ativar todas as APIs necessárias. Em seguida, clique em Criar função e insira a seguinte configuração:
  • Ambiente: 2ª geração
  • Nome da função: create-document-function-scope
  • Região: us-central-1
  • Autenticação: permitir invocações não autenticadas
Configurações para a primeira função do Cloud
Expanda a seçãoConfigurações de tempo de execução, compilação, conexões e segurança e, em Variáveis de ambiente de tempo de execução, adicione uma nova variável ATLAS_URI com sua string de conexão do MongoDB Atlas. Não se esqueça de substituir os espaços reservados para nome de usuário e senha pelas credenciais do usuário do seu banco de dados.
Em vez de adicionar suas credenciais como variáveis de ambiente em texto não criptografado, você pode armazená-las facilmente como segredos no Secret Manager. Depois de fazer isso, você poderá acessá-los a partir do seu Cloud Functions.
Clique em Avançar. É hora de adicionar a implementação da função. Abra o arquivopackage.json no painel esquerdo e substitua seu conteúdo pelo seguinte:
1{
2 "dependencies": {
3 "@google-cloud/functions-framework": "^3.0.0",
4 "mongodb": "latest"
5 }
6}
Adicionamos o pacotemongodbcomo uma dependência. O pacote é usado para distribuir o driver MongoDB Node.js que usaremos para nos conectar ao banco de dados.
Agora, alterne para o arquivo index.js e substitua o código padrão pelo seguinte:
1// Global (instance-wide) scope
2// This code runs once (at instance cold-start)
3const { http } = require('@google-cloud/functions-framework');
4const { MongoClient } = require('mongodb');
5
6http('createDocument', async (req, res) => {
7 // Function scope
8 // This code runs every time this function is invoked
9 const client = new MongoClient(process.env.ATLAS_URI);
10 client.on('connectionCreated', () => {
11 console.log('New connection created!');
12 });
13
14 // Connect to the database in the function scope
15 try {
16 await client.connect();
17
18 const collection = client.db('test').collection('documents');
19
20
21 const result = await collection.insertOne({ source: 'Cloud Functions' });
22
23 if (result) {
24 console.log(`Document ${result.insertedId} created!`);
25 return res.status(201).send(`Successfully created a new document with id ${result.insertedId}`);
26 } else {
27 return res.status(500).send('Creating a new document failed!');
28 }
29 } catch (error) {
30 res.status(500).send(error.message);
31 }
32});
Certifique-se de que o tempo de execução selecionado seja Node.js 16 e, para o ponto de entrada, substitua helloHttp por createDocument.
Por fim, clique em Deploy.

Criar a função de nuvem com conexão de banco de dados com escopo global

Go para a lista com funções e clique em Criar função novamente. Dê um nome à função create-document-global-scope. O restante da configuração deve ser exatamente o mesmo que na função anterior. Não se lembre de adicionar uma variável de ambiente chamada Atlas_URI para sua connection string. Clique emAvançar e substitua o conteúdo dopackage.json pelo mesmo código que usamos na seção anterior. Em seguida, abra index.js e adicione a seguinte implementação:
1// Global (instance-wide) scope
2// This code runs once (at instance cold-start)
3const { http } = require('@google-cloud/functions-framework');
4const { MongoClient } = require('mongodb');
5
6// Use lazy initialization to instantiate the MongoDB client and connect to the database
7let client;
8async function getConnection() {
9 if (!client) {
10 client = new MongoClient(process.env.ATLAS_URI);
11 client.on('connectionCreated', () => {
12 console.log('New connection created!');
13 });
14
15 // Connect to the database in the global scope
16 await client.connect();
17 }
18
19 return client;
20}
21
22http('createDocument', async (req, res) => {
23 // Function scope
24 // This code runs every time this function is invoked
25 const connection = await getConnection();
26 const collection = connection.db('test').collection('documents');
27
28 try {
29 const result = await collection.insertOne({ source: 'Cloud Functions' });
30
31 if (result) {
32 console.log(`Document ${result.insertedId} created!`);
33 return res.status(201).send(`Successfully created a new document with id ${result.insertedId}`);
34 } else {
35 return res.status(500).send('Creating a new document failed!');
36 }
37 } catch (error) {
38 res.status(500).send(error.message);
39 }
40});
Altere o ponto de entrada para createDocument e implemente a função.
Como você pode ver, a única diferença entre as duas implementações é onde nos conectamos ao banco de dados. Para reiterar:
  • A função que se conecta no escopo da função criará uma nova conexão em cada invocação.
  • A função que se conecta no escopo global criará novas conexões apenas em "cold starts," permitindo que algumas conexões sejam reutilizadas.
Vamos executar nossas funções e ver o que acontece! Clique emAtivar Cloud Shell na parte superior do console do Google Cloud. Execute o seguinte comando para enviar solicitações 50 para a função create-document-function-scope:
1seq 50 | xargs -Iz -n 1 -P 50 \
2 gcloud functions call \
3 create-document-function-scope \
4 --region us-central1 \
5 --gen2
Você será solicitado a autorizar o Cloud Shell a usar suas credenciais ao executar comandos. Clique em Authorize (Autorizar). Após alguns segundos, você deverá começar a ver os registros na janela do terminal sobre os documentos que estão sendo criados. Aguarde até que o comando pare de ser executado - isso significa que todas as solicitações foram enviadas.
Em seguida, execute o seguinte comando para obter os logs da função:
1gcloud functions logs read \
2 create-document-function-scope \
3 --region us-central1 \
4 --gen2 \
5 --limit 500 \
6 | grep "New connection created"
Estamos usando grep para filtrar apenas as mensagens que são registradas sempre que uma nova conexão é criada. Você deve ver que várias novas conexões foram criadas!
Terminal cloud shell
Podemos contá-los com o wc -l comando:
1gcloud functions logs read \
2 create-document-function-scope \
3 --region us-central1 \
4 --gen2 \
5 --limit 500 \
6 | grep "New connection created" \
7 | wc -l
Você deve ver o número 50 impresso na janela do terminal. Isso confirma nossa teoria de que uma conexão é criada para cada solicitação.
Vamos repetir o processo para a funçãocreate-document-global-scope.
1seq 50 | xargs -Iz -n 1 -P 50 \
2 gcloud functions call \
3 create-document-global-scope \
4 --region us-central1 \
5 --gen2
Você deve ver mensagens de registro sobre documentos criados novamente. Quando o comando terminar, execute:
1gcloud functions logs read \
2 create-document-global-scope \
3 --region us-central1 \
4 --gen2 \
5 --limit 500 \
6 | grep "New connection created"
Desta vez, você deverá ver um número significativamente menor de novas conexões. Você pode contá-las novamente com wc -l. Temos nossa prova de que estabelecer uma conexão com o banco de dados no escopo global é mais eficiente do que fazê-lo no escopo da função.
Observamos anteriormente que aumentar o número de solicitações simultâneas para um Cloud Function pode ajudar a aliviar o problema de conexões do banco de dados. Vamos expandir um pouco mais sobre isso.

Simultaneidade com o Cloud Functions 2nd gen e o Cloud Run

Por padrão, as funções do Cloud só podem processar uma solicitação por vez. No entanto, as funções do Cloud 2nd gen são executadas em um contêiner do Cloud Run. Entre outros benefícios, isso nos permite configurar nossas funções para lidar com várias solicitações simultâneas. O aumento da capacidade de simultaneidade aproxima o Cloud Functions de uma forma como os aplicativos de servidor tradicionais se comunicam com um banco de dados.
Se a instância de função oferecer suporte a solicitações simultâneas, você também poderá aproveitar o pool de conexões. Lembre-se de que o driver MongoDB que você está usando criará e manterá automaticamente um pool com conexões que as solicitações simultâneas usarão.
Dependendo do caso de uso e da quantidade de trabalho que se espera que suas funções façam, você pode ajustar:
  • As configurações de simultaneidade de suas funções.
  • O número máximo de instâncias de função que podem ser criadas.
  • O número máximo de conexões no pool mantido pelo driver do MongoDB.
E como provamos, você deve sempre declarar sua conexão com o banco de dados no escopo global para persisti-la entre as invocações.

Torne suas operações de banco de dados idempotentes em funções orientadas a eventos

Você pode ativar a repetição para suas funções orientadas a eventos. Se você fizer isso, o Cloud Functions tentará executar sua função várias vezes até que ela seja concluída com êxito ou o período de repetição termine.
Essa funcionalidade pode ser útil em muitos casos, principalmente ao lidar com falhas intermitentes. No entanto, se sua função contiver uma operação de banco de dados, executá-la mais de uma vez pode criar documentos duplicados ou outros resultados indesejados.
Vamos considerar o exemplo a seguir: A função store-message-and-notify é executada sempre que uma mensagem é publicada em um tópico de Pub/Sub especificado. A função salva a mensagem recebida como um documento no MongoDB Atlas e, em seguida, usa um serviço de terceiros para enviar um SMS. No entanto, o provedor de serviços de SMS frequentemente falha e a função gera um erro. Habilitamos novas tentativas, de modo que o Cloud Functions tenta executar nossa função novamente. Se não tivéssemos cuidado com a implementação, poderíamos duplicar a mensagem em nosso banco de dados.
Como lidamos com esses cenários? Como tornamos nossas funções seguras para tentativas repetidas? Temos que garantir que a função seja idempotente. Funções idempotentes produzem exatamente o mesmo resultado, independentemente de serem executadas uma ou várias vezes. Se inserirmos um documento de banco de dados sem uma verificação de exclusividade, tornaremos a função não idempotente.
Vamos experimentar este cenário.

Criação da função de nuvem não idempotente orientada por eventos

Go Cloud Functions e comece a configurar uma nova função:
  • Ambiente: 2ª geração
  • Nome da função: store-message-and-notify
  • Região: us-central-1
  • Autenticação: Exigir autenticação
Em seguida, clique em Adicionar trigger do Eventarc e selecione o seguinte na caixa de diálogo aberta:
  • Provedor de eventos: Cloud Pub/Sub
  • Evento: google.cloud.pubsub.topic.v1.messagePublished
Expanda Selecione um tópico do Cloud Pub/Sub e clique em Criar um tópico. Insira test-topic para a ID do tópico e, em seguida,Criar tópico.
Por fim, ative Repetir em caso de falha e clique em Salvar trigger. Observe que a função sempre tentará novamente em caso de falha, mesmo que a falha seja causada por um bug na implementação.
Adicione uma nova variável de ambiente chamada Atlas_URI com sua connection string e clique em Next.
Substitua o package.json pelo que usamos anteriormente e, em seguida, substitua o arquivoindex.js pela seguinte implementação:
1const { cloudEvent } = require('@google-cloud/functions-framework');
2const { MongoClient } = require('mongodb');
3
4// Use lazy initialization to instantiate the MongoDB client and connect to the database
5let client;
6async function getConnection() {
7 if (!client) {
8 client = new MongoClient(process.env.ATLAS_URI);
9 await client.connect();
10 }
11
12 return client;
13}
14
15cloudEvent('processMessage', async (cloudEvent) => {
16 let message;
17 try {
18 const base64message = cloudEvent?.data?.message?.data;
19 message = Buffer.from(base64message, 'base64').toString();
20 } catch (error) {
21 console.error('Invalid message', cloudEvent.data);
22 return Promise.resolve();
23 }
24
25 try {
26 await store(message);
27 } catch (error) {
28 console.error(error.message);
29 throw new Error('Storing message in the database failed.');
30 }
31
32 if (!notify()) {
33 throw new Error('Notification service failed.');
34 }
35});
36
37async function store(message) {
38 const connection = await getConnection();
39 const collection = connection.db('test').collection('messages');
40 await collection.insertOne({
41 text: message
42 });
43}
44
45// Simulate a third-party service with a 50% fail rate
46function notify() {
47 return Math.floor(Math.random() * 2);
48}
Em seguida, navegue até o tópico Pub/Sub que acabamos de criar e vá para a guiaMensagens . Publique algumas mensagens com diferentes corpos de mensagem.
Navegue de volta para suas Atlas deployments. Você pode inspecionar as mensagens armazenadas no banco de dados clicando em Procurar Coleções no bloco de cluster e, em seguida, selecionando o banco de dados deteste e a collection. Você notará que algumas das mensagens que acabou de publicar são duplicadas. Isso ocorre porque, quando a função é tentada novamente, armazenamos a mesma mensagem novamente.
Uma maneira explícita de tentar corrigir a idempotência da função é alternar as duas operações. Podemos executar a funçãonotify() primeiro e, se ela for bem-sucedida, armazenar a mensagem no banco de dados. Mas o que acontecer se a operação do banco de dados falhar? Se essa fosse uma implementação real, não poderíamos cancelar o envio de uma notificação por SMS. Então, a função ainda é não idempotente. Vamos procurar outra solução.

Usando o ID do evento e o índice exclusivo para tornar a função de nuvem idempotente

Toda vez que a função é invocada, o evento associado é passado como argumento junto com um ID exclusivo. O ID do evento permanece o mesmo mesmo quando a função é repetida. Podemos armazenar o ID do evento como um campo no documento do MongoDB. Em seguida, podemos criar um índice exclusivo nesse campo. Dessa forma, o armazenamento de uma mensagem com um ID de evento duplicado falhará.
Conecte-se ao seu banco de dados a partir do MongoDB Shell e execute o seguinte comando para criar um índice único:
1db.messages.createIndex({ "event_id": 1 }, { unique: true })
Em seguida, clique em Editar em sua função do Cloud e substitua a implementação pelo seguinte:
1const { cloudEvent } = require('@google-cloud/functions-framework');
2const { MongoClient } = require('mongodb');
3
4// Use lazy initialization to instantiate the MongoDB client and connect to the database
5let client;
6async function getConnection() {
7 if (!client) {
8 client = new MongoClient(process.env.ATLAS_URI);
9 await client.connect();
10 }
11
12 return client;
13}
14
15cloudEvent('processMessage', async (cloudEvent) => {
16 let message;
17 try {
18 const base64message = cloudEvent?.data?.message?.data;
19 message = Buffer.from(base64message, 'base64').toString();
20 } catch (error) {
21 console.error('Invalid message', cloudEvent.data);
22 return Promise.resolve();
23 }
24
25 try {
26 await store(cloudEvent.id, message);
27 } catch (error) {
28 // The error E11000: duplicate key error for the 'event_id' field is expected when retrying
29 if (error.message.includes('E11000') && error.message.includes('event_id')) {
30 console.log('Skipping retrying because the error is expected...');
31 return Promise.resolve();
32 }
33
34 console.error(error.message);
35 throw new Error('Storing message in the database failed.');
36 }
37
38 if (!notify()) {
39 throw new Error('Notification service failed.');
40 }
41});
42
43async function store(id, message) {
44 const connection = await getConnection();
45 const collection = connection.db('test').collection('messages');
46 await collection.insertOne({
47 event_id: id,
48 text: message
49 });
50}
51
52// Simulate a third-party service with a 50% fail rate
53function notify() {
54 return Math.floor(Math.random() * 2);
55}
Go ao tópico do Pub/Sub e publique mais algumas mensagens. Em seguida, inspecione seus dados no Atlas e você verá que as novas mensagens não estão mais sendo duplicadas.
Não existe uma solução única para a idempotência. Por exemplo, se você estiver usando operações de atualização em vez de inserir, convém verificar a opçãoupsert e o operador$setOnInsert.

Configurar uma conexão de rede segura

Para garantir a segurança máxima para seu Atlas cluster e Google Cloud Functions, estabelecer uma conexão segura é fundamental. Felizmente, você tem várias opções disponíveis através do Atlas que nos permitem configurar a rede privada.
Uma dessas opções é configurar o emparelhamento de rede entre o banco de dados do MongoDB Atlas e o Google Cloud. Como alternativa, você pode criar um endpoint privado usando o Private Service Connect. Ambos os métodos fornecem soluções robustas para proteger a conexão.
No entanto, é importante observar que esses recursos não estão disponíveis para uso com o cluster Atlas M0 gratuito. Para aproveitar essas medidas de segurança aprimoradas, você precisará atualizar para um cluster dedicado na camada M10 ou superior.

Resumo

Concluindo, o Cloud Functions e o MongoDB Atlas são uma combinação poderosa para criar aplicativos eficientes, escaláveis e econômicos. Seguindo as práticas recomendadas descritas neste artigo, você pode garantir que seu aplicativo seja robusto, de alto desempenho e capaz de lidar com qualquer quantidade de tráfego. Desde o uso de índices adequados até a proteção de sua rede, essas dicas ajudarão você a aproveitar ao máximo essas duas ferramentas poderosas e a criar aplicativos que sejam realmente nativos da nuvem. Portanto, comece a implementar essas melhores práticas hoje e leve seu desenvolvimento de nuvem para o próximo nível! Se ainda não tiver feito isso, você pode se inscrever no MongoDB Atlas e criar seu primeiro cluster gratuito diretamente no marketplace do Google Cloud.

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Introdução ao MongoDB e C


Sep 17, 2024 | 12 min read
Tutorial

Anúncio UDF do MongoDB para modelos do BigQuery Dataflow


Apr 02, 2024 | 4 min read
Tutorial

Configurar autenticação de e-mail/senha no MongoDB Atlas App Services


Mar 13, 2024 | 3 min read
Tutorial

Migrar do Azure CosmosDB para o MongoDB Atlas usando o Apache Kafka


May 09, 2022 | 3 min read
Sumário