satudora-dev / bloc_sample

bloc pattern sample code
0 stars 0 forks source link

Cloud Firestoreでの生理管理サービスのデータ構造の設計 #12

Open gakuh opened 5 years ago

gakuh commented 5 years ago

WHY

WHAT

TODO

REF

gakuh commented 5 years ago

サンプルデータ

JSONのイメージ


// /users/:user_id
{
"name": "hoge"
"phoneNumber": "090xxxxxxxx"
"addressPrefecture": "北海道"
"addressCity": "札幌市"
"addressRest": "中央区xxxx"
"age": "25"
}
gakuh commented 5 years ago

悩ましい点

gakuh commented 5 years ago

Cloud Firestoreは必ずしもJSONではないので、アウトプットはCloud Firestoreに実際に作ることにする。TODOを修正

sono8stream commented 5 years ago

決済情報はstripeのライブラリがstripe_customersコレクションを使用する設定になっています. 運用上コストが低そうなので,このデータ構造をそのまま用いるのが良いと考えられます.

sono8stream commented 5 years ago

https://console.firebase.google.com/u/1/project/fluttertest-8e79e/database/firestore/data~2F データ構造を一通り書き上げましたので確認お願いします. 平行してルールの検討を進めていきます.

TetsuFe commented 5 years ago

勉強がてら見ていたら気になったので質問です usersが一つのperiodsのreferenceしか持ってないように見えるけどperiodsって仕様としてそういうもの? イメージではperiodsがusersのreferenceを持っている方が自然に思えた つまり仕様として何個かの生理周期がユーザに紐づいている方が自然かと思った(勘違いならすいません)

https://console.firebase.google.com/u/1/project/fluttertest-8e79e/database/firestore/data~2Fusers~2Fhuga

sono8stream commented 5 years ago

peeiodsの各ユーザに対応するdocumentの中に、複数の生理周期を記録しておくperiodRecordsが入っています。 なのでそういった問題はないかと

TetsuFe commented 5 years ago

「peeiodsの各ユーザに対応するdocument」これがどれのことかわからなかった (追記)あ、IDがユーザIDってこと? (追記)間違えてました。hogeがユーザIDってことですかね。それなら理解できました。

sono8stream commented 5 years ago

@gakuh @TetsuFe https://console.firebase.google.com/u/1/project/fluttertest-8e79e/database/firestore/rules ルールを一応作りましたので確認お願いします.

よしおさんに共有していただいた記事のアンチパターンとなっている,getを頻繁に使う仕様になっています.

シミュレートを行うと確かに実行速度が遅いので,何らかの形で解決方法を探る必要がありそうですが,今のところ見当はついていません.

TetsuFe commented 5 years ago

resource変数っていうのを使うと今アクセスしようとしているリソースを参照できるみたい https://firebase.google.com/docs/firestore/security/secure-data?hl=ja#the_resource_variable

以下の例(上記リンクから引用)の下から4行目みたいなルールを設定できれば、getの数やdocumentPath()中のjoin等の処理を減らせそう

service cloud.firestore {
  match /databases/{database}/documents {
    match /bulletinBoard/{note} {
      // You can read any document that has a custom field named "visibility"
      // set to the string "public" or "read-only"
      allow read: if resource.data.visibility in ["public", "read-only"];
    }
    match /products/{productID}/reviews/{review} {
      allow read;
      // A user can update product reviews, but they can't change the headline.
      // Also, they should only be able to update their own product review,
      // and they still have to list themselves as an author.
      allow update: if request.resource.data.headline == resource.data.headline
                    && resource.data.authorID == request.auth.uid // こことかみたいな使い方ができそう
                    && request.resource.data.authorID == request.auth.uid;
  }
}

若干話は逸れますがFirestoreのベンチマークをどうとるのが正解かわからないので、速度の比較のやり方もわかっていない状態です。知っている人がいたら教えていただきたいです

sono8stream commented 5 years ago

@TetsuFe resourceから読む方法も考えてはいたのですが,resourceは今見ているドキュメント内のデータしか取れないんですよね.現状のデータ構造の場合,dailyLogなどの各ドキュメント側でuserIDの情報を持っていないので,resourceから読めません. これを避けるにはつまり,userIDなりuserIDへのreferenceを持つようにデータ構造を変えよう,という話になると思うので,データ構造を再検討してみます.

Firestoreのベンチマークを取る方法は僕も不明です.ただ,getを使う場合は体感でわかるレベルで実行速度が違うので,やはり避けるべきかなと.

ルールのシミュレーションは変数のトレースもできないですし,細かいデバッグ用の機能はサポートされていない気がしますね.

sono8stream commented 5 years ago

シミュレーション時の速度はあまり関係ないんですかね. resourceから読み取る検証をしてみましたが速くなっているとも思えず.

いずれにせよget,exists,getAfterは追加料金の対象になるので乱用は避けたほうが良さそうです. https://firebase.google.com/docs/firestore/pricing?hl=ja

sono8stream commented 5 years ago

dailyLogやperiod側の各ドキュメントでuidフィールドを保持するようにしました. これによりユーザー認証はドキュメント内で完結するようになったので,getを使う必要がなくなりました.

ただこの仕様にして思うこととして,[ドキュメント名をuidにする]/[ドキュメント名を自動生成のIDにしてuidフィールドを作る]のどちらを採用すべきか迷いがあります.

何か知見等あれば教えていただきたいです.

sono8stream commented 5 years ago

用途によって最適なデータ構造が全く異なるので猛烈に競技プログラミングを感じています