The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Facturia \u2014 Postgres \u2192 MongoDB ETL",
"nodes": [
{
"parameters": {},
"id": "0b8d1e00-0000-0000-0000-000000000001",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT id AS _id, name, email, phone, address, created_at AS \"createdAt\" FROM clients ORDER BY id;",
"options": {}
},
"id": "0b8d1e00-0000-0000-0000-000000000002",
"name": "PG: SELECT clients",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
480,
160
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "insert",
"collection": "clients",
"fields": "_id,name,email,phone,address,createdAt",
"options": {}
},
"id": "0b8d1e00-0000-0000-0000-000000000003",
"name": "Mongo: Insert clients",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
720,
160
],
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT id AS _id, name, description, price::float AS price, stock, category, created_at AS \"createdAt\" FROM products ORDER BY id;",
"options": {}
},
"id": "0b8d1e00-0000-0000-0000-000000000004",
"name": "PG: SELECT products",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
480,
300
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "insert",
"collection": "products",
"fields": "_id,name,description,price,stock,category,createdAt",
"options": {}
},
"id": "0b8d1e00-0000-0000-0000-000000000005",
"name": "Mongo: Insert products",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
720,
300
],
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT\n i.id AS _id,\n i.invoice_number AS \"invoiceNumber\",\n i.issued_at AS \"issuedAt\",\n i.status,\n i.total::float AS total,\n jsonb_build_object(\n '_id', c.id,\n 'name', c.name,\n 'email', c.email\n ) AS client,\n COALESCE(\n jsonb_agg(\n jsonb_build_object(\n 'productId', p.id,\n 'productName', p.name,\n 'quantity', ii.quantity,\n 'unitPrice', ii.unit_price::float,\n 'subtotal', ii.subtotal::float\n )\n ORDER BY ii.id\n ) FILTER (WHERE ii.id IS NOT NULL),\n '[]'::jsonb\n ) AS items\nFROM invoices i\nJOIN clients c ON c.id = i.client_id\nLEFT JOIN invoice_items ii ON ii.invoice_id = i.id\nLEFT JOIN products p ON p.id = ii.product_id\nGROUP BY i.id, c.id\nORDER BY i.id;",
"options": {}
},
"id": "0b8d1e00-0000-0000-0000-000000000006",
"name": "PG: SELECT invoices (with embedded items)",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
480,
460
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Normalize Postgres output for MongoDB.\n// - jsonb columns arrive as JS objects already, but defensively parse strings.\n// - Ensure issuedAt is a real Date.\nreturn items.map(({ json }) => {\n const client = typeof json.client === 'string' ? JSON.parse(json.client) : json.client;\n const itemsArr = typeof json.items === 'string' ? JSON.parse(json.items) : json.items;\n return {\n json: {\n _id: Number(json._id),\n invoiceNumber: json.invoiceNumber,\n client: {\n _id: Number(client._id),\n name: client.name,\n email: client.email,\n },\n issuedAt: new Date(json.issuedAt),\n status: json.status,\n total: Number(json.total),\n items: (itemsArr || []).map((it) => ({\n productId: Number(it.productId),\n productName: it.productName,\n quantity: Number(it.quantity),\n unitPrice: Number(it.unitPrice),\n subtotal: Number(it.subtotal),\n })),\n },\n };\n});"
},
"id": "0b8d1e00-0000-0000-0000-000000000007",
"name": "Transform invoices",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
720,
460
]
},
{
"parameters": {
"operation": "insert",
"collection": "invoices",
"fields": "_id,invoiceNumber,client,issuedAt,status,total,items",
"options": {}
},
"id": "0b8d1e00-0000-0000-0000-000000000008",
"name": "Mongo: Insert invoices",
"type": "n8n-nodes-base.mongoDb",
"typeVersion": 1.1,
"position": [
960,
460
],
"credentials": {
"mongoDb": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "done",
"name": "status",
"value": "ETL complete",
"type": "string"
}
]
},
"options": {}
},
"id": "0b8d1e00-0000-0000-0000-000000000009",
"name": "Done",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1200,
300
]
}
],
"connections": {
"Manual Trigger": {
"main": [
[
{
"node": "PG: SELECT clients",
"type": "main",
"index": 0
},
{
"node": "PG: SELECT products",
"type": "main",
"index": 0
},
{
"node": "PG: SELECT invoices (with embedded items)",
"type": "main",
"index": 0
}
]
]
},
"PG: SELECT clients": {
"main": [
[
{
"node": "Mongo: Insert clients",
"type": "main",
"index": 0
}
]
]
},
"PG: SELECT products": {
"main": [
[
{
"node": "Mongo: Insert products",
"type": "main",
"index": 0
}
]
]
},
"PG: SELECT invoices (with embedded items)": {
"main": [
[
{
"node": "Transform invoices",
"type": "main",
"index": 0
}
]
]
},
"Transform invoices": {
"main": [
[
{
"node": "Mongo: Insert invoices",
"type": "main",
"index": 0
}
]
]
},
"Mongo: Insert clients": {
"main": [
[
{
"node": "Done",
"type": "main",
"index": 0
}
]
]
},
"Mongo: Insert products": {
"main": [
[
{
"node": "Done",
"type": "main",
"index": 0
}
]
]
},
"Mongo: Insert invoices": {
"main": [
[
{
"node": "Done",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 0,
"versionId": "1"
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
mongoDbpostgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Facturia — Postgres → MongoDB ETL. Uses postgres, mongoDb. Event-driven trigger; 9 nodes.
Source: https://github.com/seif2003/UC-PostgreSQL-vs-MongoDB/blob/fc2db93ee2a7e4ef2acb9558abe72597436b1719/n8n/postgres-to-mongo.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
aula-00-mapa-do-n8n. Uses emailReadImap, stopAndError, httpRequest, graphql. Event-driven trigger; 46 nodes.
Reagendamiento_v2. Uses executeWorkflowTrigger, redis, httpRequest, n8n-nodes-evolution-api. Event-driven trigger; 89 nodes.
This workflow acts as a junior finance research analyst for a UK boutique M&A or corporate finance team. It listens for Slack messages, classifies the request, gathers company or market data, and prod
Agendamiento_v2. Uses n8n-nodes-evolution-api, redis, httpRequest, executeWorkflowTrigger. Event-driven trigger; 59 nodes.
Cancelacion_v2. Uses executeWorkflowTrigger, redis, httpRequest, n8n-nodes-evolution-api. Event-driven trigger; 46 nodes.