Docs Menu
Docs Home
/ /

チュートリアル: SQLからMongoDBへのフラグメント移行

このチュートリアルでは、FlaskアプリケーションをSQLからMongoDBに移行する方法を説明します。具体的には、このチュートリアルでは、SQLAlchemy を使用する例のブログアプリケーションを、Flask- PyMongo を使用するものに変換します。

この例アプリケーションには、次の機能が含まれています。

  • ブログ投稿の作成、編集、表示

  • ブログ記事の検索

MongoDBは、ドキュメントにデータを保存する NoSQLデータベースです。以下のリストでは、 MongoDB の主要な概念を説明しています。

  • コレクション: SQLデータベースのテーブルに似たドキュメントのグループ。スキーマを強制しません。

  • ドキュメント: データを保存するJSONのようなオブジェクト。ドキュメントには配列やネストされたサブドキュメントを含めることができます。

  • BSON : MongoDB が内部的に使用するバイナリJSON形式。 BSON は、日付やバイナリなどの追加のデータ型でJSONを拡張したものです。

次の表は、 MongoDBデータベースとSQLデータベースを比較したものです。

機能
SQL
MongoDB

スキーマ

事前定義されたテーブルと列を含む固定スキーマを強制

動的データモデルを可能にする柔軟なスキーマ

データ構造

行と列を含むテーブルにデータを保存

ドキュメントのコレクションにデータを保存

関係

テーブル間の関係を確立するために外部キーと結合を使用します

ドキュメントを他のドキュメントに埋め込みます。または参照します。結合は必要ありません

クエリ言語

構造化クエリ言語の使用(SQL)

豊富なJSONベースのクエリ言語を使用

このチュートリアルでは、次の手順を実行する方法について説明します。

  • 前提条件を確認します

  • フラグのインストール- PyMongo

  • [Flask]アプリケーションモデルを更新します

  • [Flask]アプリケーション構成を更新します

  • [Flask]アプリケーションルートを更新します

  • SQLite からのデータのエクスポート

  • MongoDBへのデータのインポート

  • [Flask] テンプレートを更新します

  • 移行したアプリケーションの実行

1

このチュートリアルには次の前提条件が必要です。

  • MongoDB はローカルマシンにインストールされています。手順については、 MongoDB Serverマニュアルの MongoDBのインストールガイドを参照してください。

  • SQLAlchemy を使用する既存の Fluskアプリケーション。このチュートリアルでは、GitHub の fluk-mongoリポジトリの例フラグアプリケーションを使用できます。

  • Python 3.7 以降。

flask-mongo例アプリケーションには、flask-mongoflask-sql の 2 つのサブフォルダが含まれています。 flask-sql フォルダーには、このチュートリアルの移行に使用できる SQLAlchemy を使用する Flukアプリケーションが含まれています。

移行を開始 する前に、次のアクションを完了してください。

  1. テーブル、関係、データ型など、 SQLデータベーススキーマを確認します。

  2. MongoDBで特別な処理を必要とする複雑なクエリと関係を識別します。

  3. データベースの ドキュメント指向 を考慮してMongoDBスキーマを設計します。 MongoDBでのスキーマ設計の詳細については、 MongoDB Serverマニュアルの「 スキーマの設計」ガイドを参照してください。

  4. 現在のSQLデータベースの完全なバックアップを作成します 。

2

Flusk- PyMongoは、 MongoDB をFlusk アプリケーションと統合する Flusk 拡張機能です。

以下のコマンドを実行中して、Flask- PyMongoをインストールします。

pip install Flask-PyMongo Flask
3

models.pyファイルの内容を次のコードで置き換えます。

from datetime import datetime
from 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}')"

このコードでは、 MongoDBのブログ投稿をモデル化する Postクラスを定義します。クラスには、次のメソッドが含まれています。

  • __init__: 各書き込みのタイトル、内容、書き込み日付、一意の識別子を設定

  • to_dict:インスタンスをMongoDBストレージの辞書に変換

  • from_dict: 辞書から Postインスタンスを作成します

  • __repr__: 書き込みの string 表現を返します

4

__init__.pyファイルの内容を次のコードで置き換えます。

from flask import Flask
from flask_pymongo import PyMongo
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
mongo = PyMongo(app)
from app import routes

このコードは、Flaskアプリケーションを初期化し、Flask- PyMongo拡張機能を通じてMongoDBを使用するようにします。

次のコードを追加して、 MongoDB設定を含むように config.pyファイルをアップデートします。

import os
class Config:
SECRET_KEY = os.urandom(24)
MONGO_URI = 'mongodb://localhost:27017/blogdb'

manage.pyファイルを削除します。このファイルはSQLのデータベース移行に使用しますが、 MongoDBには適用されません。

注意

MongoDBの移行が必要な場合は、 Builder が移行のサポートを提供します。

5

routes.pyファイルの内容を次のコードで置き換えます。

from flask import render_template, url_for, flash, \
redirect, request
from app import app, mongo
from bson.objectid import ObjectId
from app.models import Post
from 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)

このコードでは、SQLAlchemy の代わりにMongoDBを使用するようにルートを更新します。ルートは次のアクションを完了します。

  • MongoDBでのストレージに to_dict メソッドを使用して、Post インスタンスを辞書に変換する

  • 次を使用して投稿を取得する mongo.db.posts.find()

  • を使用して投稿を挿入 mongo.db.posts.insert_one()

  • 次を使用して投稿を更新します mongo.db.posts.update_one()

  • 次を使用して投稿を削除します mongo.db.posts.delete_one()

  • MongoDB の正規表現機能を使用して投稿を検索

6

export_list_tables.py という名前のPythonスクリプトを作成し、次のコードを新しいファイルに追加して、SQLiteデータベース内のすべてのテーブルを一覧表示します。

import sqlite3
# Connect to the SQLite database
db_path = 'relative/path/to/site.db'
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Query to get all table names
cursor.execute("SELECT name FROM sqlite_master WHERE \
type='table';")
tables = cursor.fetchall()
# Close the connection
conn.close()
print(tables)

このスクリプトを実行して、テーブル名を表示します。出力には post テーブルが表示されます。

データをJSONにエクスポートするには、次のコードを新しいファイルに追加して、export_to_json.py という名前の別のPythonスクリプトを作成します。

import sqlite3
import json
# Connect to the SQLite database
db_path = 'relative/path/to/site.db'
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Export data from the 'post' table
cursor.execute("SELECT * FROM post")
rows = cursor.fetchall()
# Get the column names
column_names = [description[0] for description in \
cursor.description]
# Convert to list of dictionaries
data = [dict(zip(column_names, row)) for row in rows]
# Save to a JSON file
with open('post.json', 'w') as f:
json.dump(data, f, indent=4)
# Close the connection
conn.close()

次のスクリプトを実行して、現在のディレクトリに post.jsonファイルを作成します。このファイルには、 JSON形式のエクスポートされたデータが含まれています。

7

import_to_mongo.py という名前のPythonスクリプトを作成し、次のコードを新しいファイルに追加して、 JSONファイルをMongoDBにインポートします。

from pymongo import MongoClient
import json
from 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)

このスクリプトを実行して、データをMongoDBにインポートします。スクリプトはdate_postedフィールドを日時オブジェクトに変換し、すべての投稿をMongoDBコレクションに挿入します。

注意

接続文字列mongodb://localhost:27017/blogdb は、ポート 27017 にあるローカルホスト上のMongoDBインスタンスに接続します。 MongoDB は最初にデータを書き込むと、データベースを自動的に作成します。

8

MongoDBドキュメントIDを使用するようにテンプレート ファイルを更新し、post_id=post.id のすべてのインスタンスを post_id=post._id に変更します。

9

次のコマンドを実行中して、Flaskアプリケーションを実行します。

python run.py

ウェブ ブラウザで http://127.0.0.1:5000/home に移動すると、アプリケーションにアクセスできます。

[Flask-Pymongo] の詳細については、Flask- PyMongoに関するドキュメントを参照してください。

戻る

チュートリアル: Azureコンテナ アプリへの Flusk アプリの配置