FirestoreのデータをMySQLへ移行する実践ガイド

WEB職

Node.js × Laravelで安全にデータ移行する方法

Firestore(NoSQL)から MySQL(RDB)へデータを移行するケースはそこまで多くありませんが、
**「プロトタイプはFirestore、本番や分析基盤はRDB」**という構成では避けて通れない作業です。

この記事では、実際に運用している
Firestore → JSON → MySQL
という2段階構成のデータ移行フローと、その内部ロジックを詳しく解説します。


目次

  1. 全体の流れ
  2. 実行手順とコマンド
    • Step 1: データ抽出(Firestore → JSON)
    • Step 2: データ確認(JSON → Scan)
    • Step 3: DB初期化(Reset)
    • Step 4: データ移行(JSON → MySQL)
  3. 処理の詳細ロジック
    • 移行順序
    • データ変換
    • エラーハンドリング
    • スキーマレス対策

全体の流れ

今回のデータ移行は、大きく 2ステップ構成 です。

① データ抽出(Node.js)

Firestore 管理者SDKを使い、
指定したコレクションのデータを JSONファイルとして書き出す

  • 実行スクリプト: extract_data.js
  • 出力先: backend/storage/app/firestore_data.json

② データ移行(Laravel)

Laravelの Artisan コマンドで JSON を読み込み、
MySQL用に変換しながらインサートします。

  • 実行コマンド: php artisan migrate:firestore

Firestoreと直接MySQLをつなげないことで、

  • データを目視確認できる
  • 何度でも再実行できる
  • ロジックを分離できる

というメリットがあります。


実行手順とコマンド

Step 1: データの抽出(Firestore → JSON)

Firestoreからデータを取得し、ローカルJSONとして保存します。

実行ディレクトリ

functions/

実行コマンド

cd functions
unset FIRESTORE_EMULATOR_HOST && node extract_data.js

何をしているか

  • Firestoreの指定コレクション(例: users, sessionsなど)を取得
  • JSON形式でファイルに保存

設定箇所

抽出対象のコレクションは extract_data.js 内で定義します。

const collections = [
  'users',
  'tables',
  'sessions',
  ...
]

Step 2: データの確認(JSON → Scan)

MySQLには書き込まず、
JSONの中身だけを解析・確認します。

docker exec westside_php php artisan migrate:firestore --mode=analyze

できること

  • 各コレクションの件数チェック
  • フィールド構造の把握
  • 欠損データの事前確認

👉 いきなり migrate しないのが重要です。


Step 3: データベースの準備(DB Reset)

⚠️ 注意:すべてのデータが削除されます

docker exec westside_php php artisan migrate:fresh

テスト環境・検証環境でのみ実行してください。


Step 4: データの移行(JSON → MySQL)

いよいよ本番のデータ移行です。

docker exec westside_php php artisan migrate:firestore --mode=migrate

処理内容

  • JSON読み込み
  • Firestore特有の型変換
  • 外部キーの解決
  • MySQLへインサート

処理の詳細ロジック

ここからは MigrateFirestoreData.php の内部処理について。


1. 移行の順序(外部キー対策)

外部キー制約を守るため、移行順序は非常に重要です。

  1. Users(ユーザー)
    • すべての基点。依存なし
  2. Tables(ビリヤード台)
    • 依存なし
  3. Sessions
    • User / Table に依存
  4. MiscPurchases
    • User / Session に依存
  5. TableHistories
    • User / Table / Session に依存
  6. BackDoorCodes
  7. Entries
  8. PayPayPayments

この順序を守らないと、外部キー制約で必ず失敗します。


2. データ変換処理

Firestore特有の型を、MySQL向けに変換します。

🔹 ID

  • FirestoreのドキュメントID(文字列)
  • → MySQLの VARCHAR 主キーとしてそのまま使用

🔹 Timestamp

Firestoreの

{
  "_seconds": 1700000000,
  "_nanoseconds": 0
}

を、PHPの Carbon インスタンスへ変換。

🔹 Reference

Firestoreの

users/USER_ID

のような参照は、

USER_ID

のみを抽出して外部キーにセット。


3. エラーハンドリング(不整合データ対策)

部分抽出(例: limit付き)や欠損データがあると、
参照先が存在しないケースが発生します。

そこで以下のチェックを実施。

✔ ユーザー存在チェック

  • 紐づく user_id が存在しない場合
  • そのレコードごとスキップ

✔ セッション存在チェック

  • session_id が存在しない場合
  • null にする or レコードをスキップ

👉 「止めない・落とさない」設計が重要。


4. スキーマレス対策(Firestoreあるある)

Firestoreはスキーマレスなので、

  • フィールドがある / ない
  • 型が微妙に違う

という状況が普通に起きます。

移行スクリプトでは以下を徹底。

$data['amount'] = $doc['amount'] ?? 0;
$data['memo']   = $doc['memo']   ?? null;
  • isset()
  • ?? null
  • デフォルト値指定

MySQLのスキーマに必ず合わせる


まとめ

Firestore → MySQL の移行は、

  • 一発でやろうとしない
  • JSONを挟む
  • analyze → migrate の二段構え
  • 外部キー順序を絶対守る

これだけで、失敗率がかなり下がります。

Firestoreは便利ですが、
**「あとでRDBに持っていく可能性がある」**なら、
最初から移行を見据えた設計をしておくのがおすすめです。

コメント

タイトルとURLをコピーしました