= 1024) leftSidebarOpen = false; if(window.innerWidth >= 1280) rightSidebarOpen = false"<br>:class="{ 'dark': $store.theme.dark, 'left-sidebar-closed': !leftSidebarDesktop, 'right-sidebar-closed': !rightSidebarDesktop, 'overflow-hidden': leftSidebarOpen || rightSidebarOpen, 'sidebars-closed': !leftSidebarDesktop && !rightSidebarDesktop }">
How to Copy and Sync a MongoDB Collection to PostgreSQL
Skip to content
Download Free
0" x-text="$store.bookmarks.count" class="nav-bookmarks-count" x-cloak>
Bookmarks
0">
No bookmarks yet.
Bookmarks are saved locally on this browser.
= 1280 ? rightSidebarDesktop = !rightSidebarDesktop : rightSidebarOpen = true"<br>class="nav-icon-btn"<br>:class="{ 'is-active': !(window.innerWidth >= 1280 ? rightSidebarDesktop : rightSidebarOpen) }"<br>aria-label="Toggle sidebar">
= 1280 ? !rightSidebarDesktop : !rightSidebarOpen" d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4V3z" fill="currentColor" stroke="none" />
VisuaLeaf
Download
Navigation
if (window.innerWidth
Search articles…
Preferences
Layout
Save Sidebar view
Remember if sidebars are open or closed across pages.
Save Sidebar layout preference
Enable Bookmarks
Save your favourite articles locally in this browser.
Enable Local Bookmarks
let scroll = window.scrollY;<br>let docHeight = document.documentElement.scrollHeight - window.innerHeight;<br>this.progress = docHeight > 0 ? Math.max(0, Math.min(1, scroll / docHeight)) : 0;<br>this.ticking = false;<br>});<br>}"<br>@scroll.window.passive="update()"<br>@resize.window.passive="update()"<br>x-init="update()"<br>class="fixed top-0 left-0 w-full h-[3px] z-[100] pointer-events-none">
Sync a MongoDB collection to PostgreSQL with VisuaLeaf.
I tested a MongoDB-to-PostgreSQL sync with a visits collection.<br>At first, I thought the hard part would be the sync itself. It was not. The harder part was making PostgreSQL understand the MongoDB document shape.<br>MongoDB lets one document contain strings, dates, nested objects, arrays, and an _id. PostgreSQL wants fixed columns, clear data types, and a primary key.<br>So before running the sync, I had to decide what the PostgreSQL table should look like.<br>For this test, I used VisuaLeaf Mongo Sync.<br>I used it because I wanted to set up the workflow visually: source collection, target PostgreSQL table, field mapping, and sync status. I still had to create the PostgreSQL table and check the mapping carefully, but I did not have to write a custom sync script.<br>Source Collection<br>The source was:<br>database_compare_demo.visits<br>Each MongoDB document had simple fields like:<br>_id<br>visitId<br>status<br>visitDate<br>visitReason<br>It also had nested fields:<br>patient<br>doctor<br>symptoms<br>prescriptions<br>invoice<br>labResults<br>visitDetails<br>vitals<br>clinic<br>MongoDB visits collection with nested patient, doctor, lab results, and vitals data.This is where the mapping matters. If you try to force every nested MongoDB field into separate SQL columns too early, the setup gets messy fast.<br>For this test, I used a PostgreSQL landing table.<br>PostgreSQL Table<br>I created one table:<br>CREATE TABLE public.mongo_visits_sync (<br>mongo_id TEXT PRIMARY KEY,<br>"visit_id" TEXT,<br>status TEXT,<br>"visit_date" TIMESTAMPTZ,<br>"visit_reason" TEXT,
patient JSONB,<br>doctor JSONB,<br>symptoms JSONB,<br>prescriptions JSONB,<br>invoice JSONB,<br>"lab_results" JSONB,<br>"visit_details" JSONB,<br>vitals JSONB,<br>clinic JSONB<br>);<br>I kept the simple fields as normal columns.<br>I stored the nested MongoDB objects and arrays as JSONB.<br>This was easier to test, and it kept the original document structure instead of flattening everything too early.<br>Why mongo_id Is Important<br>The PostgreSQL table needs a primary key.<br>In this setup, MongoDB _id maps to PostgreSQL mongo_id.<br>_id -> mongo_id<br>Without this, the sync cannot safely update existing rows.<br>One error I hit was:<br>SQL target has no key columns — cannot upsert idempotently<br>That means PostgreSQL did not have a usable key for the sync job.<br>The fix was to create mongo_id as the primary key and map MongoDB _id to it.<br>Field Mapping and Data Types<br>In VisuaLeaf, the mapping shows the MongoDB fields with simple source types like String, Object, and Array.<br>That matters because not every MongoDB field should become a normal text column in PostgreSQL.<br>Creating a new transformation mapping before generating the MongoDB to PostgreSQL fields.For this test, I used this logic:
MongoDB field<br>Type shown in VisuaLeaf<br>PostgreSQL column<br>PostgreSQL type
_id<br>String<br>mongo_id<br>TEXT
visitId<br>String<br>visit_id<br>TEXT
status<br>String<br>status<br>TEXT
visitDate<br>String / Date<br>visit_date<br>TIMESTAMPTZ
visitReason<br>String<br>visit_reason<br>TEXT
patient<br>Object<br>patient<br>JSONB
doctor<br>Object<br>doctor<br>JSONB
symptoms<br>Array<br>symptoms<br>JSONB
prescriptions<br>Array<br>prescriptions<br>JSONB
invoice<br>Object<br>invoice<br>JSONB
labResults<br>Array / Object<br>lab_results<br>JSONB
visitDetails<br>Object<br>visit_details<br>JSONB
vitals<br>Object<br>vitals<br>JSONB
clinic<br>Object<br>clinic<br>JSONB
Field mapping from MongoDB fields to PostgreSQL columns, including objects and arrays.The simple string fields went into normal PostgreSQL text...