4f7c88e96e6b8fc20fb54fabb4c086ee477e03df
Reviewed-on: #6
DBSyncer - MongoDB to PostgreSQL Data Synchronization
A comprehensive data synchronization tool that:
- Downloads Television data from the TVMaze API and stores it in MongoDB
- Automatically generates PostgreSQL table schemas from MongoDB document structures
- Efficiently inserts/updates MongoDB documents into PostgreSQL with intelligent type conversion
Features
Schema Generation (db/schema_generator.py)
- Automatic Schema Inference: Analyzes MongoDB documents to infer PostgreSQL types
- Type Mapping: Intelligent conversion between MongoDB and PostgreSQL types:
- Objects/Arrays → JSONB
- Dates → TIMESTAMP
- Numbers → BIGINT / DOUBLE PRECISION
- Strings → TEXT
Document Insertion
- Batch Processing: Efficiently inserts documents in configurable batches (default: 1000)
- Type Conversion: Automatic type conversion for:
- Epoch timestamps ↔ ISO datetime strings
- JSON strings ↔ Python dict/list
- ObjectId → Text
- UPSERT Support: Uses PostgreSQL
ON CONFLICT ... DO UPDATE SETfor automatic upserts - Error Handling: Detailed logging with per-row error reporting
Quick Start
Prerequisites
pip install -r requirements.txt
Configuration
Edit settings/tvsync_settings.cfg:
[dbsettings]
hostname = localhost
pgsqlport = 5432
pgsqlusername = postgres
pgsqlpassword = your_password
dbname = media_dbsync
mghostname = localhost
mgport = 27017
mgdbname = media
[database]
dbtype = pgsql
updateschema = updates
Main Scripts
update_mongodb.py
Fetches TV data from TVMaze API and stores in MongoDB:
python3 update_mongodb.py
mongodb2postgres.py
Generates PostgreSQL schemas from MongoDB collections and inserts documents:
python3 mongodb2postgres.py
This script will:
- Analyze each MongoDB collection (series, episodes, actors, characters, crew)
- Automatically create corresponding PostgreSQL tables in the
updatesschema - Insert/upsert all documents with proper type conversions
- Report progress and any errors
Usage Examples
Generate Table Schema from MongoDB Collection
from db.schema_generator import MongoToPostgresSchemaGenerator
generator = MongoToPostgresSchemaGenerator(sample_size=100)
schema = generator.analyze_collection(mongo_db, 'series')
# View the SQL
sql = generator.generate_create_table_sql('seriesdata', schema_name='dbo', pk_field='id')
print(sql)
# Create the table
generator.create_table_in_postgres(engine, 'seriesdata', schema_name='dbo', pk_field='id')
Insert Documents with Type Conversion
from db.schema_generator import MongoDocumentInserter
inserter = MongoDocumentInserter(batch_size=1000)
# From a collection
count = inserter.insert_from_collection(
engine=engine,
table_name='seriesdata',
collection=mongo_db['series'],
schema_name='dbo',
on_conflict="ON CONFLICT (id) DO UPDATE SET name=EXCLUDED.name, updated=EXCLUDED.updated",
)
print(f"Inserted {count} documents")
Architecture
Database Classes (db/functions.py)
settype: Manages database engine creation and API configurationdbmongo: Handles MongoDB connections and operationsDbexec: Executes raw SQL queries and batch updates
Schema Generator (db/schema_generator.py)
MongoToPostgresSchemaGenerator: Infers and creates table schemasMongoDocumentInserter: Handles document insertion with type conversion
API Integration (api/)
- TVMaze API client for fetching show, episode, cast, and crew data
- TheTVDB API client (optional)
Performance Optimizations
- Batch Inserts: Uses SQLAlchemy's parameterized queries for efficient batch operations
- Transactional Inserts: Groups inserts in transactions to reduce database overhead
- Column Type Awareness: Converts data to match target column types, avoiding casting overhead
- Connection Pooling: Reuses database connections (pool_size=20, max_overflow=20)
- UPSERT Operations: Uses PostgreSQL's
ON CONFLICTfor atomic insert-or-update
Troubleshooting
MetaData Schema Argument Error
If you see sqlalchemy.exc.ArgumentError: Could not parse SQLAlchemy URL, ensure:
- Use
MetaData(schema="updates")instead ofMetaData("updates") - Pass full connection strings to
create_engine(), not schema names
Type Conversion Errors
The inserter automatically handles:
- Datetime strings → epoch timestamps (for BIGINT columns)
- Epoch ints → datetime objects (for TIMESTAMP columns)
- JSON strings → Python dicts (for JSONB columns)
If type errors persist, check that:
- Table schema matches MongoDB document fields
- Column types are correctly inferred from sample documents
- Use appropriate
on_conflictclauses for upserts
Column Name Case Sensitivity
PostgreSQL stores unquoted identifiers as lowercase. The inserter automatically:
- Lowercases column names in
ON CONFLICTclauses - Uses case-insensitive matching when mapping MongoDB fields to PostgreSQL columns
Contributing
When modifying:
- Schema inference: Update
MongoToPostgresSchemaGenerator.TYPE_MAPPINGfor new type support - Type conversion: Extend
MongoDocumentInserter.convert_value()for custom conversions - Database operations: Use parameterized queries via
text()to prevent SQL injection - Error handling: Add specific exception types to improve debugging
License
See LICENSE file for details.
Description
Languages
Python
99.9%