LoginSignup
32
15

More than 3 years have passed since last update.

firestoreをmigrationするcommand lineツール作った。後悔はしていない。

Posted at

Gakuです。

就職決まりました。また東京舞い戻りです。
就業するとプライベート開発がはかどらなくなるので、なんとか今のうちに就業しつつ爆速で開発できる環境を整えようと奮闘しています。
僕の中で爆速開発のベースサービスと期待しまくっているfirestoreですが、NoSQLということもあり、なかなかスケールしにくいという印象を持っておりました。
Railsみたいに「migrationツールがあれば。。。」と考えていたんですが、なかったのでサクッと作ってみました。後悔はしていません。

作ろうとした経緯

@1amageek さんの「[Qiita]Firebaseのマイグレーション」を読んでいて、「migrationツールあればokじゃね?」と思ったので作りました。firestoreの思想とかは完全無視してるのでマサカリ怖いですが後悔はしていません。

作ったもの

npmで公開しています。まだあまり検証できていないし、ちょっとmigrationファイルの書き方をミスるとエラーが出る状態なので、ご利用される方は挙動を把握した上で慎重にご活用ください。(今後どんどん改良していきます。)
また、githubのissueいただければ、検討いたしますのでよろしくお願いします!(日本語でok!)
[npm]firestore-migration

firestoreの勘所

Field追加どうすん?

firestoreはテーブル定義等を行う必要がなく、どんどんデータをぶち込める仕様です。なので、例えばField追加したいと思った際は

user
|-user1{name:'gaku1', age:27}
|-user2{name:'gaku2', age:30, location: 'nara'}
|-user3{name:'gaku3', age:35}

こんな感じで、データの歯抜けが起こってしまいます。
こういう状態になってしまうと、「データがない場合は、こう表示する!」という処理をフロントで記述する必要があり、ちょっと面倒です。
あとRDB慣れていると気持ち悪いです(; ・`д・´)

そこでfirestore-migration

firestore-migrationで全documentにfieldの追加を行うことができるように実装しています。

{
   "method": "ADD",
   "collection": "user",
   "params": [
      {"name": "location", "value": ""}
   ]
}

みたいにmigrationファイルを定義し、「fsmigrate -m .」を実施すると、

user
|-user1{name:'gaku1', age:27, location: ''}
|-user2{name:'gaku2', age:30, location: 'nara'}
|-user3{name:'gaku3', age:35, location: ''}

で全documentにFieldを生やしてくれます。やったぜ(´ω`)!

fieldの削除どうすんの?

firestoreでは一度格納したデータのFieldを削除することは基本的にできません。
なので、age field[number]を削除して、tosi field[string]にしたいな~っとおもった際、

user
|-user1{name:'gaku1', age:27, location: '', tosi: '27'}
|-user2{name:'gaku2', age:30, location: 'nara', tosi: '30'}
|-user3{name:'gaku3', age:35, location: '', tosi: '35'}

と、age fieldを放置してtosiを生やす形で対応します。これでもいいのですが、キモイので、できればage削除したいですよね?

そこでfirestore-migration

Fieldを削除する際はこんな感じでmigrationファイルを定義します。

{
   "method": "DEL",
   "collection": "user",
   "params": [
      {"name": "age"},
   ]
}

これを実行すると、

user
|-user1{name:'gaku1', location: '', tosi: '27'}
|-user2{name:'gaku2', location: 'nara', tosi: '30'}
|-user3{name:'gaku3', location: '', tosi: '35'}

age fieldを削除することができます。やったぜ!

集計どうすんの?

firestoreのQueryは貧相です。なので、集計操作とかSQLだと簡単にできることが、firestoreでは基本的にできません。
なので「[firebase]集約クエリ」というテクニックを使って、集計データをfirestore上にデータとして保持した上で対応したりします。
ただ、この集約クエリ、「リリース後どうすんの?」って問題があります。これから新たに生成するデータに対しては集計処理をしてくれますが、これまでのデータに対しては集計処理を行うことができません。なので、頑張ってscriptを組んでデータ改変して対応する方法があるかと思うのですが、いちいちscript組むのも面倒ですし、リスキーです。

そんな時にfirestore-migration

user
|-doc1{name: gaku}
|-doc2{name: gakuko}

purchese
|-pdoc1{uid: doc1, price: 500}
|-pdoc2{uid: doc2, price: 600}
|-pdoc3{uid: doc1, price: 700}
         ↓
user
|-doc1{name: gaku, priceall: 1200}
|-doc2{name: gakuko, priceall: 600}

こんな感じに集計データを生やしたい場合、

{
   "method": "AGG_COLLECTION",
   "collection": "user",
   "params": [
           {"name": "priceall", "aggCollection": "purchese", "if": "{uid} === $ID", "aggField": "price"}
   ]
}

これでok!全ドキュメントに集計したデータを格納してくれます。楽ちんちん。

その他の機能

その他にも僕の中で「あったら楽なのにな~」っていう機能をいろいろ詰め込んでますので、詳しくはREADMEを見てもらえればと思います。
[npm]firestore-migration

注意点

transaction処理について

全データを読み込んで、全データに書き込みという方法をとっています。できればtransactionを利用して適用という方法を取りたかったのですが、firestoreには1回のtransaction処理のオペレート数に上限500回という制限があるので、いろいろ考えた上でtransaction処理は行わず処理しています。
データの整合性は完全に無視していますが、今後何かしらの対応はしないといけないと思っています。

データの読み書きについて

全データを読み込んで、全データに適用という方法をとっています。データ数が増えるとその分の利用回数が増えるので、「使用量」については十分注意っす。

collecitonの読み取りについて

collectionの読み取りには最近実装されたcollectionGroup機能を活用して読み取りを行っています。
現状、collectionGroupは横断的な検索しかできないため、

user
|-doc1{name:gaku}-user
                   |-doc1{age:27}

みたいにcollection名がかぶると、すべてのデータに適用する仕様としています。
例えば、firestore-migrationのADDを適用すると

user
|-doc1{name:gaku, location:''}-user
                   |-doc1{age:27, location:''}

という挙動になってしまうわけです。ご注意ください。
(※ここはfirestoreのcollectionGroupがパスの制限機能を付けてくれることを期待しつつ、現状放置しています。)

おわりに

まだまだ問題の多いツールですが、一旦「僕自身なら利用できるツール!」になったので記事書いてみました。
エラーハンドリングめんどいので放置している点、多数ありますが今後ぼちぼち対応していく予定です。

なんかほしい機能とか、「ここはこうした方が良い」とか「こういう処理でエラー出たから対応しろ糞野郎!」とかあったらissueくれれば大変うれしいです(´ω`)
僕自身がどんどん活用していくためのツールなので、今後改良は続けていこうと思ってます。

それにしても「firestore楽しい。一人実装の友firestore!」

それではまた( ゚Д゚)ノシ

32
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
15