Como migrar seu aplicativo Flask do SQL para o MongoDB
Muhammed Ali9 min read • Published Jun 28, 2024 • Updated Jun 28, 2024
APLICATIVO COMPLETO
Avalie esse Tutorial
A migração de um aplicativo Spark do SQL para o MongoDB envolve várias etapas, pois os dois sistemas de banco de dados têm paradigmas diferentes. Este artigo irá orientá-lo na conversão de um aplicativo de blog MongoDB existente que usa SQLAlchemy para Flask-PyMongo para integrar o MongoDB com o aplicativo MongoDB. Explicaremos as alterações feitas em cada arquivo e as razões por trás delas.
O MongoDB é um banco de dados NoSQL conhecido por seu tipo de estrutura em estilo de documento e facilidade de uso.
Conceitos chave
- Collection: Analogamente às tabelas em bancos de dados SQL, as collection no MongoDB armazenam documentos. No entanto, diferentemente das tabelas, as collection não impõem um esquema, o que significa que cada documento pode ter campos diferentes.
- Documentos: esta é a principal estrutura de dados no MongoDB, semelhante às linhas em bancos de dados SQL, mas mais complexa. Documentos são objetos semelhantes a JSON que podem conter arrays e subdocumentos aninhados.
- BSON: a representação binária do JSON é usada internamente pelo MongoDB. Ele estende o JSON com tipos de dados adicionais, como data e binário.
funcionalidade | SQL | MongoDB |
Esquema | Aplica um esquema fixo com tabelas e colunas predefinidas | Sem esquema, permitindo modelos de dados flexíveis e dinâmicos |
Estrutura de dados | Armazena dados em tabelas com linhas e colunas | Armazena dados em collection de documentos |
Relacionamentos | Usa chaves estrangeiras e uniões para estabelecer relações entre tabelas | Incorpora documentos dentro de outros documentos ou faz referência a eles, mas não tem junções |
Linguagem de query | Usa linguagem de query estruturada (SQL) | Usa uma linguagem de query rica baseada em JSON |
Antes de migrar o aplicativo Spark do SQL para o MongoDB, é necessário um planejamento minucioso para garantir uma transição tranquila e preservar a integridade dos dados.
O planejamento adequado ajuda a identificar possíveis bloqueadores e desenvolver estratégias para resolvê-los.
- Configure o ambiente do MongoDB
- Avalie o esquema e os relacionamentos SQL atuais: revise o esquema do banco de dados existente, incluindo tabelas, relacionamentos e tipos de dados. Identifique queries e relacionamentos complexos que podem exigir cuidado especial no MongoDB.
- Defina o esquema do MongoDB: projete o esquemado MongoDB considerando a natureza orientada a documentos do banco de dados. Mapeie tabelas e relacionamentos SQL para coleções e documentos do MongoDB.
- Faça backup dos dados existentes: crie um backup completo do banco de dados SQL atual para evitar a perda de dados. Garanta que os processos de backup sejam confiáveis e possam ser restaurados, se necessário.
- Estratégia de transformação e migração de dados: escolha uma ferramenta de migração ou escreva scripts personalizados para lidar com a migração de dados, como faremos neste artigo.
- Atualizar o código do aplicativo Flask: modifique os modelos do Flask para usar o MongoDB em vez do SQLAlchemy. Atualize rotas, formulários e modelos para trabalhar com a nova estrutura de dados. Teste cada módulo do aplicativo para garantir a compatibilidade com o MongoDB.
- Teste pós-migração: teste minuciosamente o aplicativo para garantir que todas as funcionalidades estejam funcionando conforme o esperado. Monitore o desempenho e otimize queries e índices no MongoDB.
O aplicativo a ser migrado é um aplicativo de blog Flusk com as seguintes funcionalidades:
- Criação, edição e visualização de postagens de blog
- Pesquisando por postagens de blog
Antes de integrar o MongoDB com um aplicativo Flask, a primeira etapa é instalar o MongoDB em sua máquina local. O MongoDB fornece guias de instalaçãodetalhados para várias versões do sistema operacional.
Depois de instalar o MongoDB, a próxima etapa é configurá-lo para funcionar em seu aplicativo Firefly. Isso envolve a instalação do pacote
Flask-PyMongo
e a configuração da conexão com o servidor mongo db local.MongoDB é uma extensão do MongoDB que facilita o uso de instâncias do MongoDB em seu aplicativo do MongoDB.
Instale usando o pip:
1 pip install Flask-PyMongo Flask
Você também pode instalar o MongoDB, caso ainda não o tenha feito.
- modelos.py: Define o modeloPost usando SQLAlchemy com atributos para id, título, conteúdo e date_posted
- __init__.py: inicializa o aplicativo Frask e o SQLAlchemy
- forms.py: Contém definições de formulário usando Flask-WTF
- manager.py: Gerencia migrações de banco de dados usando Flusk-Script e Flusk-Migrate
- rotas.py: contém as definições de rota e lógica para lidar com solicitações
O que você fará é fazer uma cópia da pasta que contém o projeto antigo. Usaremos a estrutura de arquivos atual e apenas substituiremos o código atual por algum novo código.
Vá para models.py e cole o seguinte código:
1 from datetime import datetime 2 from bson.objectid import ObjectId 3 class Post: 4 def __init__(self, title, content, date_posted=None, _id=None): 5 self.title = title 6 self.content = content 7 self.date_posted = date_posted if date_posted else datetime.utcnow() 8 self._id = _id if _id else ObjectId() 9 10 def to_dict(self): 11 return { 12 "title": self.title, 13 "content": self.content, 14 "date_posted": self.date_posted, 15 "_id": self._id 16 } 17 18 @staticmethod 19 def from_dict(data): 20 return Post( 21 title=data.get('title'), 22 content=data.get('content'), 23 date_posted=data.get('date_posted'), 24 _id=data.get('_id') 25 ) 26 27 def __repr__(self): 28 return f"Post('{self.title}', '{self.date_posted}')"
Este código define uma classe
Post
que modela um blog post para uso com um MongoDB database, utilizando os BSON types do PyMongo. A classe inclui um inicializador (método__init__
) que define o título, oconteúdo, adata de publicaçãoe um identificador exclusivo para cada publicação. Se a data publicada ou o identificador não for fornecido durante a instanciação, será padronizado o horário UTC atual e um novo ObjectId
, respectivamente. A classe também fornece um métodoto_dict
para converter uma instância em um formato de dicionário adequado para o armazenamento do MongoDB e um método estáticofrom_dict
para criar uma instância Post a partir de um dicionário. Além disso, o método__repr__
é definido para oferecer uma representação de string clara da postagem, útil para depuração e registro.O uso disso é para o manuseio de dados de postagens de blog em um aplicativo da Web Flask que usa o MongoDB como banco de dados. A conversão das instâncias
Post
de e para o formato de dicionário permite uma interação fácil com o armazenamento orientado a documentos do MongoDB.Cole o código a seguir em seu arquivo __init__.py. O aplicativo Flask é inicializado para usar o MongoDB por meio da extensão Flask-PyMongo. A instância do PyMongo (mongo) é configurada com o aplicativo Flask que habilita o suporte ao MongoDB. As rotas do aplicativo são importadas para definir os pontos de extremidade de URL e seus manipuladores associados.
1 from flask import Flask 2 from flask_pymongo import PyMongo 3 from config import Config 4 5 6 app = Flask(__name__) 7 app.config.from_object(Config) 8 mongo = PyMongo(app) 9 10 11 from app import routes
Além disso, atualize a classe
Config
em seu config.py para incluir as configurações do MongoDB:1 import os 2 class Config: 3 SECRET_KEY = os.urandom(24) 4 MONGO_URI = 'mongodb://localhost:27017/blogdb'
manager.py é usado para migrações de banco de dados no SQL, que não é diretamente aplicável ao MongoDB, portanto, você pode excluir o arquivo. Se você precisar de migrações, o beanie ODM fornecerá algum suporte para migrações com MongoDB.
1 from flask import render_template, url_for, flash, redirect, request 2 from app import app, mongo 3 from bson.objectid import ObjectId 4 from app.models import Post 5 from app.forms import PostForm 6 7 8 9 def home(): 10 """ 11 Render the home page with a list of all posts. 12 """ 13 posts_data = mongo.db.posts.find() 14 posts = [Post.from_dict(post) for post in posts_data] 15 return render_template("index.html", posts=posts) 16 17 18 19 def new_post(): 20 """ 21 Handle the creation of a new post. Render the new post form and process the form submission. 22 23 """ 24 form = PostForm() 25 if form.validate_on_submit(): 26 post = Post(title=form.title.data, content=form.content.data) 27 mongo.db.posts.insert_one(post.to_dict()) 28 flash("Your post has been created!", "success") 29 return redirect(url_for("home")) 30 return render_template("post.html", title="New Post", form=form) 31 32 33 34 def post(post_id): 35 """ 36 Display a single post by its ID. 37 """ 38 post_data = mongo.db.posts.find_one_or_404({"_id": ObjectId(post_id)}) 39 post = Post.from_dict(post_data) 40 return render_template("detail.html", post=post) 41 42 43 44 def edit_post(post_id): 45 """ 46 Handle the editing of an existing post. Render the edit post form and process the form submission. 47 """ 48 post_data = mongo.db.posts.find_one_or_404({"_id": ObjectId(post_id)}) 49 post = Post.from_dict(post_data) 50 form = PostForm() 51 if form.validate_on_submit(): 52 updated_post = { 53 "$set": {"title": form.title.data, "content": form.content.data} 54 } 55 mongo.db.posts.update_one({"_id": ObjectId(post_id)}, updated_post) 56 flash("Your post has been updated!", "success") 57 return redirect(url_for("post", post_id=post_id)) 58 elif request.method == "GET": 59 form.title.data = post.title 60 form.content.data = post.content 61 return render_template("edit_post.html", title="Edit Post", form=form) 62 63 64 65 def delete_post(post_id): 66 """ 67 Handle the deletion of a post by its ID. 68 """ 69 mongo.db.posts.delete_one({"_id": ObjectId(post_id)}) 70 flash("Your post has been deleted!", "success") 71 return redirect(url_for("home")) 72 73 74 75 def search(): 76 """ 77 Handle the search functionality for posts. Search for posts by title or content. 78 """ 79 query = request.args.get("query") 80 posts_data = mongo.db.posts.find( 81 { 82 "$or": [ 83 {"title": {"$regex": query, "$options": "i"}}, 84 {"content": {"$regex": query, "$options": "i"}}, 85 ] 86 } 87 ) 88 posts = [Post.from_dict(post) for post in posts_data] 89 return render_template("index.html", posts=posts)
Para tornar o aplicativo Flask compatível com o MongoDB, foram feitas várias modificações nas rotas para interagir com o MongoDB em vez do SQLAlchemy. Em primeiro lugar, as instâncias da classe Post agora são convertidas em dicionários usando o método to_dict para armazenamento no MongoDB. A rota home recupera todos os posts da coleção do MongoDB usando
mongo.db.posts.find()
, converte-os em instâncias de Post usando o métodofrom_dict
e, em seguida, renderiza-os.Para criar novas publicações na rota new_post, os dados da publicação são inseridos no MongoDB com
mongo.db.posts.insert_one(post.to_dict())
. Para recuperar, editar e excluir postagens, rotas, postagens, edit_post
e delete_post
use os métodos de consulta do MongoDB(find_one_or_404
, update_one
e delete_one
) com ObjectId
para lidar com os identificadores únicos . A rota Atlas Search executa um Atlas Search de texto em títulos e conteúdo usando os recursos de regex do MongoDB, garantindo que as publicações correspondentes à query sejam buscadas e renderizadas.O processo de migração envolve exportar dados do banco de dados SQL existente e importá-los para o MongoDB. Começaremos exportando os dados do SQLite. No GitHub, você encontrará o arquivo db que usaremos neste tutorial.
Se estiver usando meu arquivo db, execute o seguinte código para consultar o banco de dados e listar todas as tabelas e determinar seus nomes.
1 import sqlite3 2 3 4 # Connect to the SQLite database 5 db_path = 'relative/path/to/site.db' 6 conn = sqlite3.connect(db_path) 7 cursor = conn.cursor() 8 9 # Query to get all table names 10 cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") 11 tables = cursor.fetchall() 12 13 # Close the connection 14 conn.close() 15 16 print(tables)
Este código Python acima se conecta ao seu banco de dados SQLite existente especificado no caminho
db_path and
recupera os nomes de todas as tabelas dentro dele e fecha a conexão. A query SQL SELECT name FROM sqlite_master WHERE type='table';
é executada para buscar os nomes de todas as tabelas no banco de dados. Você deve ter post como sua saída.Depois disso, execute o código abaixo para exportar os dados para um arquivo JSON.
1 import sqlite3 2 import json 3 4 # Connect to the SQLite database 5 db_path = 'relative/path/to/site.db' 6 conn = sqlite3.connect(db_path) 7 cursor = conn.cursor() 8 9 # Export data from the 'post' table 10 cursor.execute("SELECT * FROM post") 11 rows = cursor.fetchall() 12 13 # Get the column names 14 column_names = [description[0] for description in cursor.description] 15 16 # Convert to list of dictionaries 17 data = [dict(zip(column_names, row)) for row in rows] 18 19 # Save to a JSON file 20 with open('post.json', 'w') as f: 21 json.dump(data, f, indent=4) 22 23 # Close the connection 24 conn.close()
Este código Python se conecta ao seu banco de dados SQLite, extrai todos os dados da tabela depostagem, converte em um formato JSON e os salva em um arquivo. Um objeto de cursor é criado a partir desta conexão para executar comandos SQL. A query SQL
SELECT * FROM post
é usada para buscar todas as linhas da tabela de postagem e os resultados são armazenados na variável de linhas. A variável column_names
é utilizada para extrair os nomes das colunas do atributo descrição do cursor. Cada linha é então combinada com os nomes das colunas para criar uma lista de dicionários, onde cada dicionário representa uma linha da tabela. E, finalmente, a lista é salva como um arquivo JSON chamado post.json usando a funçãojson.dump()
.Após a execução, você receberá um arquivo JSON (post.json) com a seguinte aparência:
1 [ 2 { 3 "id": 1, 4 "title": " Superworm (Zophobas morio)", 5 "content": "Superworms, scientifically known as Zophobas morio, are the larval stage of a darkling beetle species...", 6 "date_posted": "2024-05-14 18:03:43.219562" 7 }, 8 { 9 "id": 2, 10 "title": "MongoDB article", 11 "content": "MongoDB is a widely-used NoSQL database known for its flexibility...", 12 "date_posted": "2024-05-14 18:04:57.884181" 13 }, 14 { 15 "id": 3, 16 "title": "Unique Techniques in Farming", 17 "content": "Modern farming has evolved in various ways…", 18 "date_posted": "2024-05-14 18:07:12.665001" 19 }, 20 { 21 "id": 4, 22 "title": " Examples of NoSQL Databases", 23 "content": "NoSQL databases have improved the way...", 24 "date_posted": "2024-05-14 18:08:28.759601" 25 }, 26 { 27 "id": 5, 28 "title": "d", 29 "content": "d", 30 "date_posted": "2024-05-18 18:06:59.767954" 31 } 32 ]
Agora você pode importar este arquivo JSON para seu banco de dados MongoDB. Aqui está um script para ajudá-lo com isso:
1 from pymongo import MongoClient 2 import json 3 from datetime import datetime 4 5 def import_json_to_mongo(db_name, collection_name, json_path): 6 client = MongoClient("mongodb://localhost:27017/") 7 db = client[db_name] 8 9 def convert_date(data): 10 # Update 'date_posted' field to datetime object 11 for item in data: 12 if 'date_posted' in item: 13 item['date_posted'] = datetime.strptime(item['date_posted'], '%Y-%m-%d %H:%M:%S.%f') 14 return data 15 16 with open(json_path, 'r') as f: 17 data = json.load(f) 18 data = convert_date(data) 19 db[collection_name].insert_many(data) 20 21 client.close() 22 23 if __name__ == "__main__": 24 db_name = 'blogdb' 25 collection_name = 'posts' 26 json_path = 'flask-mongo/post.json' 27 import_json_to_mongo(db_name, collection_name, json_path)
A connection string
mongodb://localhost:27017/blogdb
se conecta à sua instância do MongoDB em execução no localhost na porta 27017 e usa o banco de dados "blogdb". Se o banco de dados especificado não existir, o MongoDB o criará automaticamente quando você armazenar os dados pela primeira vez.Para os modelos, você só precisa alterar a variável para id. Você alterará todas as instâncias de
post_id=post.id
para post_id=post._id
.Agora você pode executar o aplicativo com o seguinte comando:
1 python run.py
A migração de um aplicativo Flask do SQL para o MongoDB envolve um profundo entendimento das diferenças entre os dois sistemas de banco de dados e, em seguida, o planejamento para garantir uma transição tranquila. Este artigo forneceu um guia passo a passo sobre como converter um aplicativo de blogFlask existente usando o SQLAlchemy para usar oFlask-PyMongo para integrar o MongoDB ao aplicativoFlask. Centrámo-nos principalmente em cobrir as alterações necessárias a cada ficheiro. Em um cenário real, haveria a necessidade de construir um esquema de documento a partir de um esquema tabular com junções e várias consultas. Embora este seja um aplicativo simples, este tutorial aborda as etapas necessárias para ter uma migração bem-sucedida.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.