Pourquoi Migrer de MongoDB vers PostgreSQL ?
Le choix entre MongoDB et PostgreSQL dépend souvent des besoins spécifiques d'une application. MongoDB est un système de gestion de bases de données NoSQL qui offre une grande flexibilité et une scalabilité élevée, parfait pour les applications à faible latence et aux gros volumes de données non structurées. Cependant, PostgreSQL est un SGBD traditionnel ACID (Atomicité, Cohérence, Isolation, Durabilité) avec une forte prise en charge des requêtes complexes et des transactions critiques.
Au quotidien, un développeur peut avoir besoin de migrez sa base de données MongoDB vers PostgreSQL pour plusieurs raisons :
- Réglementation et Conformité : Certains secteurs (finance, santé, gouvernement) ont des exigences strictes en matière de conformité qui peuvent nécessiter une base de données relationnelle.
- Sécurité : PostgreSQL offre un niveau élevé de sécurité avec des fonctionnalités comme l'authentification par mot de passe fort et les droits d'accès granulaires, ce qui peut être crucial pour certains applications sensibles.
- Performances : Pour certaines charges de travail, une base de données relationnelle peut offrir des performances supérieures en raison de son modèle structuré.
Un cas d'usage concret est une application e-commerce où les transactions sont critiques et nécessitent une haute fiabilité et des performances élevées. En miguant de MongoDB vers PostgreSQL, l'équipe peut bénéficier d'un contrôle transactionnel plus robuste, un meilleur suivi des modifications et une meilleure intégration avec d'autres systèmes basés sur la relation.
Prerequis
Avant de commencer la migration, assurez-vous que vous avez les connaissances suivantes :
- PostgreSQL : Connaissance avancée du langage SQL et des concepts de gestion de bases de données relationnelles.
- MongoDB : Familiarité avec le modèle NoSQL et les fonctionnalités spécifiques de MongoDB.
- Python (optionnel) : Si vous migrez un projet Python, connaissances en Python sont nécessaires.
Les outils suivants doivent être installés :
- PostgreSQL 12 ou ultérieure
- MongoDB 4.4 ou ultérieure
- Python 3.8 ou ultérieure (si nécessaire)
Concepts fondamentaux
Collections et Tables
MongoDB utilise des collections pour stocker les documents, tandis que PostgreSQL utilise des tables.
-- Création d'une table dans PostgreSQL
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL
);
Documents et Enregistrements
Un document MongoDB est similaire à un enregistrement SQL, mais avec une structure flexible.
-- Insertion d'un enregistrement dans PostgreSQL
INSERT INTO users (name, email) VALUES ('John Doe', 'john.doe@example.com');
Indexes
MongoDB et PostgreSQL utilisent les index pour améliorer la performance des requêtes.
-- Création d'un index sur un champ dans PostgreSQL
CREATE INDEX idx_email ON users(email);
Mise en pratique : projet fil rouge
Nous allons construire un gestionnaire de tâches simple en Python qui utilise une base de données relationnelle. Le projet comprendra les opérations CRUD (Create, Read, Update, Delete).
Étape 1 : Installation des dépendances
pip install psycopg2-binary flask
Étape 2 : Création du modèle
Créez un fichier models.py :
## models.py
import psycopg2
def get_connection():
return psycopg2.connect(
dbname="tasks_db",
user="your_user",
password="your_password",
host="localhost"
)
def create_table():
conn = get_connection()
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS tasks (
id SERIAL PRIMARY KEY,
title VARCHAR(100) NOT NULL,
description TEXT,
completed BOOLEAN DEFAULT FALSE
)
""")
conn.commit()
cur.close()
conn.close()
def add_task(title, description):
conn = get_connection()
cur = conn.cursor()
cur.execute("INSERT INTO tasks (title, description) VALUES (%s, %s)", (title, description))
conn.commit()
cur.close()
conn.close()
def get_tasks():
conn = get_connection()
cur = conn.cursor()
cur.execute("SELECT * FROM tasks")
tasks = cur.fetchall()
cur.close()
conn.close()
return tasks
def update_task(task_id, title=None, description=None, completed=None):
conn = get_connection()
cur = conn.cursor()
set_clause = []
params = []
if title:
set_clause.append(f"title = %s")
params.append(title)
if description:
set_clause.append(f"description = %s")
params.append(description)
if completed is not None:
set_clause.append(f"completed = %s")
params.append(completed)
set_str = ', '.join(set_clause)
cur.execute(f"UPDATE tasks SET {set_str} WHERE id = %s", (task_id,) + tuple(params))
conn.commit()
cur.close()
conn.close()
def delete_task(task_id):
conn = get_connection()
cur = conn.cursor()
cur.execute("DELETE FROM tasks WHERE id = %s", (task_id,))
conn.commit()
cur.close()
conn.close()
Étape 3 : Création de l'API
Créez un fichier app.py :
## app.py
from flask import Flask, request, jsonify
import models
app = Flask(__name__)
@app.route('/tasks', methods=['POST'])
def add_task():
data = request.json
title = data.get('title')
description = data.get('description')
models.add_task(title, description)
return jsonify({"message": "Task added successfully"}), 201
@app.route('/tasks', methods=['GET'])
def get_tasks():
tasks = models.get_tasks()
return jsonify(tasks)
@app.route('/tasks/<int:task_id>', methods=['PUT'])
def update_task(task_id):
data = request.json
title = data.get('title')
description = data.get('description')
completed = data.get('completed')
models.update_task(task_id, title, description, completed)
return jsonify({"message": "Task updated successfully"})
@app.route('/tasks/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
models.delete_task(task_id)
return jsonify({"message": "Task deleted successfully"})
if __name__ == '__main__':
models.create_table()
app.run(debug=True)
Étape 4 : Exécution
python app.py
Accédez à http://127.0.0.1:5000/tasks pour tester les API.
Erreurs frequentes et debugging
Erreur 1 : Connexion échouée
Message d'erreur :
psycopg2.OperationalError: could not connect to server: FATAL: role "your_user" does not exist
Code incorrect :
conn = psycopg2.connect(
dbname="tasks_db",
user="your_user",
password="your_password",
host="localhost"
)
Correction :
Assurez-vous que le rôle your_user existe dans PostgreSQL.
Erreur 2 : Syntaxe SQL incorrecte
Message d'erreur :
psycopg2.errors.SyntaxError: syntax error at or near ")"
Code incorrect :
cur.execute("INSERT INTO tasks (title, description) VALUES (%s, %s)", (title, description))
Correction : Assurez-vous que la requête SQL est correctement formée.
Erreur 3 : Type de données inattendu
Message d'erreur :
psycopg2.DataError: invalid input syntax for integer: "abc"
Code incorrect :
cur.execute("INSERT INTO tasks (id, title) VALUES (%s, %s)", (task_id, title))
Correction : Assurez-vous que les types de données correspondent.
Pour aller plus loin
1. Transactions avancées
Apprenez comment gérer des transactions complexes dans PostgreSQL pour garantir l'intégrité des données lors d'opérations multiples.
2. Partitionnement et sharding
Explorez les techniques de partitionnement et sharding en PostgreSQL pour gérer des charges de travail massives.
3. ORM avancé
Utilisez un ORM comme SQLAlchemy pour simplifier l'accès à la base de données et améliorer la productivité.
Défi pratique
Créez une application web complète utilisant Flask et PostgreSQL pour gérer des utilisateurs et leurs tâches. Ajoutez les fonctionnalités suivantes :
- Inscription et connexion d'utilisateurs
- Authentification avec JWT (JSON Web Tokens)
- Gestion des tâches par utilisateur
N'oubliez pas de mettre en place des tests unitaires pour chaque fonctionnalité.