MONGODB FIND_ONE_AND_UPDATE - Buscar e Atualizar em Uma Operação
O que é este Node?
O MONGODB FIND_ONE_AND_UPDATE é o node responsável por buscar um documento e atualizá-lo em uma única operação atômica, retornando o documento atualizado.
Por que este Node existe?
Buscar e depois atualizar em operações separadas pode causar race conditions. O MONGODB FIND_ONE_AND_UPDATE existe para:
- Operação atômica: Buscar e atualizar de forma segura sem race conditions
- Retornar documento: Ver o documento atualizado imediatamente
- Upsert: Criar documento se não existir (insert + update em uma operação)
- Evitar duplicação: Garantir que apenas um documento seja modificado
Como funciona internamente?
Quando o MONGODB FIND_ONE_AND_UPDATE é executado, o sistema:
- Valida configuração: Verifica se as credenciais MongoDB foram fornecidas
- Estabelece conexão: Conecta ao servidor MongoDB usando as credenciais
- Seleciona coleção: Acessa a coleção especificada no banco de dados
- Processa query e update: Substitui variáveis em ambos os objetos
- Converte _id: Transforma strings de ObjectId quando necessário
- Executa findOneAndUpdate: Busca, atualiza e retorna em uma operação atômica
- Aplica $set automático: Envolve o update em operador $set
- Suporta upsert: Se upsert:true e não encontrar, cria novo documento
- Retorna documento atualizado: Usa returnDocument:'after'
- Fecha conexão: Encerra a conexão com MongoDB
Código interno (mongodb.executor.ts:225-248):
private async findOneAndUpdate(
db: Db,
collectionName: string,
query: any,
update: any,
options: any,
context: ExecutionContext,
): Promise<any> {
const replacedQuery = this.replaceObjectVariables(query, context.variables);
const replacedUpdate = this.replaceObjectVariables(update, context.variables);
const parsedQuery = this.parseMongoQuery(replacedQuery);
const collection = db.collection(collectionName);
const result = await collection.findOneAndUpdate(
parsedQuery,
{ $set: replacedUpdate },
{
upsert: options.upsert || false,
returnDocument: 'after',
},
);
return result.value;
}
Quando você DEVE usar este Node?
Use MONGODB FIND_ONE_AND_UPDATE sempre que precisar buscar E atualizar atomicamente:
Casos de uso
- Incrementar contador: "Buscar e incrementar visualizações de um post"
- Upsert: "Atualizar se existir, criar se não existir"
- Evitar race conditions: "Garantir atualização atômica"
- Ver resultado: "Atualizar e retornar documento modificado"
Quando NÃO usar MONGODB FIND_ONE_AND_UPDATE
- Atualizar múltiplos: Use MONGODB UPDATE para vários documentos
- Não precisa ver resultado: Use MONGODB UPDATE (mais rápido)
- Substituir completamente: Use MONGODB FIND_ONE_AND_REPLACE
- Apenas buscar: Use MONGODB FIND_ONE sem modificar
Parâmetros Detalhados
operation (string, obrigatório)
O que é: Define qual operação MongoDB será executada. Para buscar e atualizar, use "findOneAndUpdate".
Padrão: Nenhum (obrigatório)
Flow completo para testar:
{
"name": "Teste MongoDB FindOneAndUpdate - Operation",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "mongodb_1",
"type": "mongodb",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Atualizar Produto",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "loja"
},
"collection": "produtos",
"query": { "_id": "507f1f77bcf86cd799439011" },
"update": { "estoque": 15 },
"responseVariable": "produtoAtualizado"
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "✅ Produto: {{produtoAtualizado.nome}}\nNovo estoque: {{produtoAtualizado.estoque}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "mongodb_1" },
{ "source": "mongodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: 1. Execute o flow com um _id válido 2. Espere: "✅ Produto: Nome Novo estoque: 15"
config (object, obrigatório)
O que é: Objeto contendo as credenciais e configurações de conexão com o MongoDB.
Estrutura:
- connectionString (string): String de conexão completa MongoDB
- OU host, port, user, password: Configuração individual
- database (string, obrigatório): Nome do banco de dados
Flow completo para testar:
{
"name": "Teste MongoDB FindOneAndUpdate - Config",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "mongodb_1",
"type": "mongodb",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Atualizar com Auth",
"operation": "findOneAndUpdate",
"config": {
"host": "localhost",
"port": 27017,
"database": "crm",
"user": "admin",
"password": "senha123"
},
"collection": "clientes",
"query": { "email": "joao@example.com" },
"update": { "ultimoAcesso": "{{now}}" },
"responseVariable": "cliente"
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "Cliente {{cliente.nome}} - Último acesso atualizado"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "mongodb_1" },
{ "source": "mongodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: 1. Configure MongoDB com autenticação 2. Execute o flow 3. Espere: "Cliente João Silva - Último acesso atualizado"
collection (string, obrigatório)
O que é: Nome da coleção MongoDB onde o documento será buscado e atualizado.
Flow completo para testar:
{
"name": "Teste MongoDB FindOneAndUpdate - Collection",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "mongodb_1",
"type": "mongodb",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Atualizar na Coleção",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "ecommerce"
},
"collection": "pedidos",
"query": { "numero": "PED-2024-001" },
"update": { "status": "enviado" },
"responseVariable": "pedido"
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar Status",
"parameters": {
"message": "Pedido {{pedido.numero}} - Status: {{pedido.status}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "mongodb_1" },
{ "source": "mongodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: 1. Execute o flow 2. Espere: "Pedido PED-2024-001 - Status: enviado"
query (object, obrigatório)
O que é: Filtro para encontrar o documento a ser atualizado. Apenas o primeiro documento encontrado será modificado.
Flow completo para testar:
{
"name": "Teste MongoDB FindOneAndUpdate - Query",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "mongodb_1",
"type": "mongodb",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Buscar e Atualizar",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "blog"
},
"collection": "posts",
"query": {
"slug": "primeiro-post",
"ativo": true
},
"update": {
"visualizacoes": 101,
"ultimaVisualizacao": "{{now}}"
},
"responseVariable": "post"
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "Post: {{post.titulo}}\nVisualizações: {{post.visualizacoes}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "mongodb_1" },
{ "source": "mongodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: 1. Execute o flow 2. Espere: "Post: Primeiro Post Visualizações: 101"
update (object, obrigatório)
O que é: Objeto contendo os campos e valores a serem atualizados. Automaticamente usa operador $set.
Flow completo para testar:
{
"name": "Teste MongoDB FindOneAndUpdate - Update",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "mongodb_1",
"type": "mongodb",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Atualizar Campos",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "crm"
},
"collection": "clientes",
"query": { "_id": "507f1f77bcf86cd799439011" },
"update": {
"telefone": "11999998888",
"endereco": {
"rua": "Rua Nova, 789",
"cidade": "São Paulo"
},
"dataAtualizacao": "{{now}}",
"ativo": true
},
"responseVariable": "cliente"
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "✅ Cliente {{cliente.nome}} atualizado\nTelefone: {{cliente.telefone}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "mongodb_1" },
{ "source": "mongodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: 1. Execute o flow com _id válido 2. Espere: "✅ Cliente João Silva atualizado Telefone: 11999998888"
upsert (boolean, opcional)
O que é: Se true, cria um novo documento se nenhum for encontrado (INSERT + UPDATE).
Padrão: false
Flow completo para testar:
{
"name": "Teste MongoDB FindOneAndUpdate - Upsert",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "mongodb_1",
"type": "mongodb",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Upsert Config",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "app"
},
"collection": "configuracoes",
"query": { "chave": "smtp_host" },
"update": {
"valor": "smtp.gmail.com",
"dataAtualizacao": "{{now}}"
},
"upsert": true,
"responseVariable": "config"
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "✅ Configuração {{config.chave}} = {{config.valor}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "mongodb_1" },
{ "source": "mongodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: 1. Execute o flow (mesmo se chave não existir) 2. Espere: "✅ Configuração smtp_host = smtp.gmail.com"
responseVariable (string, opcional)
O que é: Nome da variável onde o documento atualizado será armazenado.
Padrão: Se não especificado, resultado não é armazenado
Flow completo para testar:
{
"name": "Teste MongoDB FindOneAndUpdate - Response Variable",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "mongodb_1",
"type": "mongodb",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Salvar Resultado",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "loja"
},
"collection": "produtos",
"query": { "_id": "507f1f77bcf86cd799439011" },
"update": { "ultimaAtualizacao": "{{now}}" },
"responseVariable": "produtoAtualizado"
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Usar Variável",
"parameters": {
"message": "Produto: {{produtoAtualizado.nome}}\nPreço: R$ {{produtoAtualizado.preco}}\nAtualizado em: {{produtoAtualizado.ultimaAtualizacao}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "mongodb_1" },
{ "source": "mongodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: 1. Execute o flow 2. Espere: "Produto: Nome Preço: R$ X Atualizado em: ..."
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| operation | string | Sim | Tipo de operação MongoDB ("findOneAndUpdate") |
| config | object | Sim | Configuração de conexão MongoDB |
| collection | string | Sim | Nome da coleção |
| query | object | Sim | Filtro para encontrar documento |
| update | object | Sim | Campos a serem atualizados |
| upsert | boolean | Não | Criar se não existir (padrão: false) |
| responseVariable | string | Não | Variável para armazenar documento |
Exemplo 1: Incrementar Visualizações de Post
Objetivo: Buscar post e incrementar contador de visualizações atomicamente
JSON para Importar
{
"name": "Incrementar Visualizações de Post",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_slug",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Slug do Post",
"parameters": {
"message": "Digite o slug do post:",
"variable": "postSlug"
}
}
},
{
"id": "mongodb_update",
"type": "mongodb",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Incrementar Views",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "blog"
},
"collection": "posts",
"query": {
"slug": "{{postSlug}}",
"publicado": true
},
"update": {
"$inc": { "visualizacoes": 1 },
"ultimaVisualizacao": "{{now}}"
},
"responseVariable": "post"
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Post Encontrado?",
"conditions": [
{
"variable": "post",
"operator": "not_equals",
"value": "null",
"targetNode": "message_success"
}
],
"defaultTarget": "message_not_found"
}
},
{
"id": "message_success",
"type": "message",
"position": { "x": 700, "y": 50 },
"data": {
"label": "Sucesso",
"parameters": {
"message": "📖 {{post.titulo}}\n\n👁️ Visualizações: {{post.visualizacoes}}\n✍️ Autor: {{post.autor}}"
}
}
},
{
"id": "message_not_found",
"type": "message",
"position": { "x": 700, "y": 150 },
"data": {
"label": "Não Encontrado",
"parameters": {
"message": "❌ Post não encontrado ou não publicado"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_slug" },
{ "source": "input_slug", "target": "mongodb_update" },
{ "source": "mongodb_update", "target": "condition_1" },
{ "source": "message_success", "target": "end_1" },
{ "source": "message_not_found", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite o slug do post:
Usuário: primeiro-post
Sistema: 📖 Meu Primeiro Post
👁️ Visualizações: 156
✍️ Autor: João Silva
Exemplo 2: Upsert de Configuração
Objetivo: Atualizar configuração se existir, criar se não existir
JSON para Importar
{
"name": "Upsert de Configuração",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_chave",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Chave Config",
"parameters": {
"message": "Digite a chave da configuração:",
"variable": "chave"
}
}
},
{
"id": "input_valor",
"type": "input",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Valor Config",
"parameters": {
"message": "Digite o valor:",
"variable": "valor"
}
}
},
{
"id": "mongodb_upsert",
"type": "mongodb",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Salvar Config",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "app"
},
"collection": "configuracoes",
"query": {
"chave": "{{chave}}"
},
"update": {
"chave": "{{chave}}",
"valor": "{{valor}}",
"dataAtualizacao": "{{now}}"
},
"upsert": true,
"responseVariable": "config"
}
},
{
"id": "message_success",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Confirmação",
"parameters": {
"message": "✅ Configuração salva!\n\n🔑 Chave: {{config.chave}}\n💾 Valor: {{config.valor}}\n🕐 Atualizado: {{config.dataAtualizacao}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_chave" },
{ "source": "input_chave", "target": "input_valor" },
{ "source": "input_valor", "target": "mongodb_upsert" },
{ "source": "mongodb_upsert", "target": "message_success" },
{ "source": "message_success", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite a chave da configuração:
Usuário: smtp_host
Sistema: Digite o valor:
Usuário: smtp.gmail.com
Sistema: ✅ Configuração salva!
🔑 Chave: smtp_host
💾 Valor: smtp.gmail.com
🕐 Atualizado: 2024-01-15T14:30:00.000Z
Exemplo 3: Atualizar Status de Pedido
Objetivo: Buscar pedido por número e atualizar status com histórico
JSON para Importar
{
"name": "Atualizar Status de Pedido",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_numero",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Número do Pedido",
"parameters": {
"message": "Digite o número do pedido:",
"variable": "numeroPedido"
}
}
},
{
"id": "input_status",
"type": "input",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Novo Status",
"parameters": {
"message": "Digite o novo status (enviado/entregue/cancelado):",
"variable": "novoStatus"
}
}
},
{
"id": "mongodb_update",
"type": "mongodb",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Atualizar Pedido",
"operation": "findOneAndUpdate",
"config": {
"connectionString": "mongodb://localhost:27017",
"database": "ecommerce"
},
"collection": "pedidos",
"query": {
"numero": "{{numeroPedido}}"
},
"update": {
"status": "{{novoStatus}}",
"dataAtualizacaoStatus": "{{now}}",
"$push": {
"historico": {
"status": "{{novoStatus}}",
"data": "{{now}}"
}
}
},
"responseVariable": "pedido"
}
},
{
"id": "message_success",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Confirmação",
"parameters": {
"message": "✅ Pedido atualizado!\n\n📦 Número: {{pedido.numero}}\n📊 Status: {{pedido.status}}\n💰 Total: R$ {{pedido.total}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_numero" },
{ "source": "input_numero", "target": "input_status" },
{ "source": "input_status", "target": "mongodb_update" },
{ "source": "mongodb_update", "target": "message_success" },
{ "source": "message_success", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite o número do pedido:
Usuário: PED-2024-001
Sistema: Digite o novo status (enviado/entregue/cancelado):
Usuário: enviado
Sistema: ✅ Pedido atualizado!
📦 Número: PED-2024-001
📊 Status: enviado
💰 Total: R$ 299.90
Resposta do Node
Quando documento é encontrado e atualizado:
{
"_id": "507f1f77bcf86cd799439011",
"nome": "Produto Atualizado",
"preco": 2499.90,
"estoque": 15,
"dataAtualizacao": "2024-01-15T14:30:00.000Z"
}
Quando documento NÃO é encontrado (sem upsert):
null
Boas Práticas
✅ SIM:
- Use findOneAndUpdate para operações atômicas (evita race conditions)
- Armazene em
responseVariablepara ver o documento atualizado - Use
upsert: truequando quiser "criar se não existir" - Sempre verifique se o resultado não é
nullantes de acessar campos - Use para incrementar contadores ($inc) de forma segura
- Combine com CONDITION para tratar caso documento não seja encontrado
❌ NÃO:
- Não use quando precisa atualizar múltiplos documentos (use UPDATE)
- Não assuma que sempre retornará um documento (pode ser null)
- Não esqueça de tratar caso de documento não encontrado
- Não use quando não precisa ver o resultado (UPDATE é mais rápido)
- Não ignore o retorno - pode ser null se query não encontrou nada
Dicas
💡 Dica 1: O documento retornado é a versão ATUALIZADA (após as modificações)
💡 Dica 2: Use upsert: true para padrão "criar ou atualizar" (muito útil para configs)
💡 Dica 3: Operação é atômica - não há risco de race condition entre busca e update
💡 Dica 4: Se retornar null, o documento não foi encontrado (mesmo com upsert, ainda retorna null em alguns casos)
💡 Dica 5: Perfeito para incrementar contadores, atualizar timestamps, etc
Próximos Nodes
→ MONGODB FIND_ONE - Apenas buscar sem atualizar → MONGODB UPDATE - Atualizar múltiplos documentos → MONGODB FIND_ONE_AND_REPLACE - Substituir documento completo → MONGODB INSERT - Criar novo documento