Visão geral
Este tutorial mostra como migrar um aplicativo Firefly de SQL para MongoDB. Especificamente, o tutorial converte um aplicativo de blog de exemplo que usa SQLAlchemy em um que usaFlask-PyMongo.
O aplicativo de exemplo inclui os seguintes recursos:
Criação, edição e visualização de publicações no blog
Pesquisando publicações no blog
Entendendo o MongoDB
MongoDB é um banco de dados NoSQL que armazena dados em documentos. A lista a seguir descreve os principais conceitos do MongoDB :
Coleções: Grupos de documentos, semelhantes a tabelas em bancos de dados SQL. As coleções não impõem um esquema.
Documentos: objetos semelhantes a JSON que armazenam dados. Os documentos podem conter arrays e subdocumentos aninhados.
BSON: formato JSON binário que o MongoDB usa internamente. O BSON estende o JSON com tipos de dados adicionais, como data e binário.
A tabela a seguir compara bancos de dados MongoDB e SQL:
funcionalidade | SQL | MongoDB |
|---|---|---|
Esquema | Força um esquema fixo com tabelas e colunas predefinidas | Esquemas flexÃveis que permitem modelos de dados dinâmicos |
Estrutura de dados | Armazena dados em tabelas com linhas e colunas | Armazena dados em coleções de documentos |
Relacionamentos | Usa chaves estrangeiras e participações para estabelecer relacionamentos entre tabelas | Incorpora documentos dentro de outros documentos ou referência a eles, sem a necessidade de junções |
Linguagem de query | Usa linguagem de query estruturada (SQL) | Usa uma linguagem de query rica baseada em JSON |
Tutorial
Este tutorial mostra como concluir as seguintes etapas:
Verifique os pré-requisitos
Instalar o Flusk-PyMongo
Atualizar os modelos de aplicativo Spark
Atualize a configuração do aplicativo Flask
atualizar as rotas do aplicativo Pipeline
Exportar dados do SQLite
Importar dados para o MongoDB
Atualizar os modelos do Frasco
Executar o aplicativo migrado
Verifique os pré-requisitos
Este tutorial requer os seguintes pré-requisitos:
MongoDB instalado na sua máquina local. Consulte o guia Instalar MongoDB no manual do MongoDB Server para obter instruções.
Um aplicativo Flask existente que usa SQLAlchemy. Você pode usar o exemplo de aplicativo Flask do repositório flask-mongo no GitHub para este tutorial.
Python 3.7 ou posterior.
O aplicativo de exemplo flask-mongo contém duas subpastas, flask-mongo e flask-sql. A pasta flask-sql contém um aplicativo Spark que usa SQLAlchemy, que você pode usar para a migração neste tutorial.
Antes de iniciar a migração, conclua as seguintes ações:
Revise seu esquema de banco de dados SQL, incluindo tabelas, relacionamentos e tipos de dados.
Identifique queries e relacionamentos complexos que podem exigir cuidado especial no MongoDB.
Crie seu esquema MongoDB considerando a natureza orientada a documentos do banco de dados. Para saber mais sobre o projeto de esquema no MongoDB, consulte o guia Designando seu esquema no manual do MongoDB Server.
Crie um backup completo do seu banco de dados SQL atual.
Atualizar os modelos de aplicativo Spark
Substitua o conteúdo do seu arquivo models.py pelo seguinte código:
from datetime import datetimefrom bson.objectid import ObjectId
class Post: def __init__(self, title, content, date_posted=None, _id=None): self.title = title self.content = content self.date_posted = date_posted if date_posted \ else datetime.utcnow() self._id = _id if _id else ObjectId()
def to_dict(self): return { "title": self.title, "content": self.content, "date_posted": self.date_posted, "_id": self._id }
staticmethod def from_dict(data): return Post( title=data.get('title'), content=data.get('content'), date_posted=data.get('date_posted'), _id=data.get('_id') )
def __repr__(self): return f"Post('{self.title}', \ '{self.date_posted}')"Este código define uma classe Post que modela uma publicação no blog para o MongoDB. A classe inclui os seguintes métodos:
__init__: Define o tÃtulo, conteúdo, data de publicação e identificador exclusivo para cada publicaçãoto_dict: Converte uma instância em um dicionário para armazenamento MongoDBfrom_dict: cria uma instânciaPosta partir de um dicionário__repr__: retorna uma representação de string da publicação
Atualize a configuração do aplicativo Flask
Substitua o conteúdo do seu arquivo __init__.py pelo seguinte código:
from flask import Flaskfrom flask_pymongo import PyMongofrom config import Config
app = Flask(__name__)app.config.from_object(Config)mongo = PyMongo(app)
from app import routesEste código inicializa o aplicativo MongoDB para usar o MongoDB por meio da extensão MongoDB-PyMongo.
Atualize seu arquivo config.py para incluir as configurações do MongoDB adicionando o seguinte código:
import os
class Config: SECRET_KEY = os.urandom(24) MONGO_URI = 'mongodb://localhost:27017/blogdb'Exclua o arquivo manage.py. Você usa esse arquivo para migrações de banco de dados no SQL, que não se aplica ao MongoDB.
Observação
Se você precisar de migrações para o MongoDB, o Beanie ODM fornecerá suporte de migração.
atualizar as rotas do aplicativo Pipeline
Substitua o conteúdo do seu arquivo routes.py pelo seguinte código:
from flask import render_template, url_for, flash, \ redirect, requestfrom app import app, mongofrom bson.objectid import ObjectIdfrom app.models import Postfrom app.forms import PostForm
app.route("/")app.route("/home")def home(): posts_data = mongo.db.posts.find() posts = [Post.from_dict(post) for post in posts_data] return render_template("index.html", posts=posts)
app.route("/post/new", methods=["GET", "POST"])def new_post(): form = PostForm() if form.validate_on_submit(): post = Post(title=form.title.data, content=form.content.data) mongo.db.posts.insert_one(post.to_dict()) flash("Your post has been created!", "success") return redirect(url_for("home")) return render_template("post.html", title="New Post", form=form)
app.route("/post/<post_id>")def post(post_id): post_data = mongo.db.posts.find_one_or_404( {"_id": ObjectId(post_id)}) post = Post.from_dict(post_data) return render_template("detail.html", post=post)
app.route("/post/<post_id>/edit", methods=["GET", "POST"])def edit_post(post_id): post_data = mongo.db.posts.find_one_or_404( {"_id": ObjectId(post_id)}) post = Post.from_dict(post_data) form = PostForm() if form.validate_on_submit(): updated_post = { "$set": {"title": form.title.data, "content": form.content.data} } mongo.db.posts.update_one( {"_id": ObjectId(post_id)}, updated_post) flash("Your post has been updated!", "success") return redirect(url_for("post", post_id=post_id)) elif request.method == "GET": form.title.data = post.title form.content.data = post.content return render_template("edit_post.html", title="Edit Post", form=form)
app.route("/post/<post_id>/delete", methods=["POST"])def delete_post(post_id): mongo.db.posts.delete_one({"_id": ObjectId(post_id)}) flash("Your post has been deleted!", "success") return redirect(url_for("home"))
app.route("/search", methods=["GET", "POST"])def search(): query = request.args.get("query") posts_data = mongo.db.posts.find( { "$or": [ {"title": {"$regex": query, "$options": "i"}}, {"content": {"$regex": query, "$options": "i"}}, ] } ) posts = [Post.from_dict(post) for post in posts_data] return render_template("index.html", posts=posts)Este código atualiza as rotas para usar MongoDB em vez de SQLAlchemy. As rotas concluem as seguintes ações:
Converta instâncias
Postem dicionários usando o métodoto_dictpara armazenamento no MongoDBRecuperar publicações usando
mongo.db.posts.find()Insira publicações usando
mongo.db.posts.insert_one()Atualizar publicações usando
mongo.db.posts.update_one()Excluir publicações usando
mongo.db.posts.delete_one()Pesquise publicações usando os recursos de regex do MongoDB
Exportar dados do SQLite
Crie um script Python denominado export_list_tables.py para listar todas as tabelas em seu banco de dados SQLite adicionando o seguinte código a um novo arquivo:
import sqlite3
# Connect to the SQLite databasedb_path = 'relative/path/to/site.db'conn = sqlite3.connect(db_path)cursor = conn.cursor()
# Query to get all table namescursor.execute("SELECT name FROM sqlite_master WHERE \ type='table';")tables = cursor.fetchall()
# Close the connectionconn.close()
print(tables)Execute este script para exibir os nomes da sua tabela. O resultado mostra a tabela post.
Crie outro script Python denominado export_to_json.py para exportar os dados para JSON adicionando o seguinte código a um novo arquivo:
import sqlite3import json
# Connect to the SQLite databasedb_path = 'relative/path/to/site.db'conn = sqlite3.connect(db_path)cursor = conn.cursor()
# Export data from the 'post' tablecursor.execute("SELECT * FROM post")rows = cursor.fetchall()
# Get the column namescolumn_names = [description[0] for description in \ cursor.description]
# Convert to list of dictionariesdata = [dict(zip(column_names, row)) for row in rows]
# Save to a JSON filewith open('post.json', 'w') as f: json.dump(data, f, indent=4)
# Close the connectionconn.close()Execute este script para criar o arquivo post.json no diretório atual. Este arquivo contém seus dados exportados no formato JSON.
Importar dados para o MongoDB
Crie um script Python denominado import_to_mongo.py para importar o arquivo JSON para o MongoDB adicionando o seguinte código a um novo arquivo:
from pymongo import MongoClientimport jsonfrom datetime import datetime
def import_json_to_mongo(db_name, collection_name, json_path): client = MongoClient("mongodb://localhost:27017/") db = client[db_name]
def convert_date(data): # Update 'date_posted' field to datetime object for item in data: if 'date_posted' in item: item['date_posted'] = datetime.strptime( item['date_posted'], '%Y-%m-%d %H:%M:%S.%f') return data
with open(json_path, 'r') as f: data = json.load(f) data = convert_date(data) db[collection_name].insert_many(data)
client.close()
if __name__ == "__main__": db_name = 'blogdb' collection_name = 'posts' json_path = 'flask-mongo/post.json' import_json_to_mongo(db_name, collection_name, json_path)Execute este script para importar seus dados para MongoDB. O script converte o campo date_posted em um objeto de data/hora e insere todas as publicações na coleção MongoDB .
Observação
A string de conexão mongodb://localhost:27017/blogdb se conecta à sua instância do MongoDB no localhost na porta 27017. O MongoDB cria o banco de dados automaticamente quando você grava dados pela primeira vez.
Recursos adicionais
Para aprender mais sobre o Flask-Pymongo, consulte a documentação do Flask-PyMongo.