はじめに
どうも、@1amageekです。
これは僕が実践で利用しているテクニックの一つです。応用範囲が広いので、まとめることにしました。
Cloud Firestoreの設計で困るところ
- ルールがめんどくさい
- ルールによって構造を変えなければならない
特に問題なのはReadですね。やっぱりセキュアに保ちたいドキュメントをルートコレクションに配置することはできないし、かと行ってサブコレクションにすると横断的にQueryかけないし
と言うことで、ブログの構造について考えてみましょう。
今までのブログの構造
RDBであれば、例えばデータベースの構造はこんな感じかな?
article table
id | title | body | is_published | author |
---|---|---|---|---|
0 | hoge | hoge | false | 1amageek |
1 | hoge1 | hoge | true | 1amageek |
2 | hoge3 | hoge | true | 1amageek |
3 | hoge4 | hoge | true | 1amageek |
公開・非公開はis_published
で管理するような形。
Firestoreなら次の二つが考えられる。
// /version/1/article/0
{
title: "hoge",
body: "hoge",
isPublished: true,
author: "1amageek"
}
// もしくは
// /version/1/user/1amageek/article/0
{
title: "hoge",
body: "hoge",
isPublished: true,
author: "1amageek"
}
どっちがいいでしょうか?
前者は、検索性に優れているけど、isPublished === true
を入れ忘れただけの簡単なヒューマンエラーでサービス潰す可能性ありますよね?😇
僕ならやりたくない。と言うことで、後者にしましょう。
いや待てよ。。。🤔
公開した時に必ず全文検索を噛ませないといけない。。orz
このくらいはCloud Firestoreだけでやりたいじゃん。
Cloud Firestoreの特性を使えばできますよ
ではどちらの構造を使えばいいでしょうか?
正解はどちらも使う
次の構造をみてください。
// 未公開時の記事はuserのSubCollectionに
// /version/1/user/1amageek/article/0
{
title: "hoge",
body: "hoge",
isPublished: true,
author: "1amageek"
}
// 公開時の記事はRootCollectionに
// /version/1/article/0
{
title: "hoge",
body: "hoge",
author: "1amageek"
}
Cloud Firestoreには__WriteBatch__と呼ばれる機能が入っています。二つのノードを同時に安全に更新できることで、一つのノードを更新・一つのノードへは追加を同時できます。
他の手段として、CloudFunctionsに任せるのもいいかもしれません。次のノードをトリガーにセットして
/version/1/user/1amageek/article/${article_id}
isPublished == true
なら、次のノードへデータを渡す。
/version/1/article/${article_id}
これでセキュアかつ、横断的な検索が可能なブログを作ることが可能となります。
Cloud Firestoreについて気になり始めたら次もどうぞ