前回は Flask + Appengine という観点でアプリ開発を始め方について説明しましたが、
番外編ではアプリ移植の際に手間をかけたデータ移行について説明します。
今回移植した GMappers というアプリは元々 MySQL 上にデータを保存していたため、
Appengine に移植するにあたりデータを移行する必要がありました。
よく知られているようです。
しかし、bulkloader.py は CSV をインポートするという仕組みであるため、
MySQL → CSV → Appengine というステップを踏む必要があります。
つまり、今回のケースでは
- MySQL から CSV を抽出するプログラム
- CSV をモデル化して Appengine に登録するプログラム
が必要になります。
また、この方法では ReferenceProperty を使って他のデータを参照するのは難しいようです。
もう少しデータ移行について調べていったところ Appengine の提供する
remote_api というライブラリがこの問題を解決できることに気づきました。
remote_api を利用することで、ローカル環境から Appengine 環境のデータを操作することができます。
※ remote_api は remote_api_shell コマンドなどで利用されています。
というわけで、remote_api を利用して開発したのが gaerunner というツールです。
gaerunner は指定したプログラムを Appengine 環境につないで実行することができます。
これを利用すると
- ローカルの DB から Appengine へデータ移行する
- Appengine からローカルの DB にデータを抜き出す
- Appengine 上のデータを他のモデルに変換する (データ移行する)
などの処理を簡単に実現することができます。
gaerunner を使うには
- gaerunner をインストールする (easy_install gaerunner)
- appengine アプリケーションで remote_api の使用を許可する (app.yaml 内で指定する)
という手順を踏む必要があります。
ここではセットアップについては割愛します。
前回の記事を読んで環境を構築するか、自分で調べて環境を作ってみて下さい。
では、早速 MySQL から Appengine へのデータ移行スクリプトを準備します。
import _mysql
from google.appengine.ext import db
class Map(db.Model):
map_id = db.IntegerProperty(required=True)
name = db.StringProperty(required=True)
description = db.TextProperty()
cn = _mysql.connect(host, user, passwd, db)
cn.query(‘SELECT * FROM maps’)
map_rs = cn.store_result()
for i in range(map_rs.num_rows()):
r = map_rs.fetch_row()[0]
map = Map(map_id=int(r[0]),
name=unicode(r[1], ‘utf-8’),
description=unicode(r[2], ‘utf-8’))
map.put()
このスクリプトでは、MySQL の maps テーブルからレコードを取り出し
各レコードを Map モデルとして保存(put)しています。
このスクリプトを gaerunner を使って次のように実行します。
% bin/gaerunner gmappers import_from_mysql.py
※ gmappers の部分はアプリケーション ID を指定して下さい
上記を実行すると gaerunner は remote_api を経由して
Map データを Appengine 環境に保存します。
これにより MySQL から Appengine へのデータ移行が実現されます。