ゆるいケアを投稿・閲覧・実施できるアプリ「ラムネ」をfirestoreで設計してみた

こんにちは。[もぐめっと](https://mogmet.com)です。

今回は今日のAppでラムネというゆるケアアプリを紹介されていたのでそのアプリをfirestoreで実装するとしたらどんな設計になるかを考えてみました。

## アプリ紹介

ざっくりいうと、ゆるケアという実施すると心が癒やされるアクションがたくさんあり、その中から好きなものを選んで実施して心を整えるといったアプリになります。
早速画面を見てみましょう。

サークルという分類の中に...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/b1305959-4328-50da-04b3-c823f5e02312.png)

ユーザが投稿したたくさんのゆるケアがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/0d481ace-759b-bd89-c7bf-d83649bffa43.png)

ゆるケア詳細を見ると実施する内容が記載されています。スキしたり、自分のゆるケアリストに追加といったことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/e786d290-427b-80d8-e08a-450b86b8b0c3.png)

チェックをタップして、気分を選ぶことによってゆるケアの記録をつけることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/143b6b99-aa87-30ec-37ec-da1f431e005a.png)

記録をつけるとやってみたリストに追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/4fee454d-a371-28b4-b025-2148be825061.png)

ゆるケアは自分で投稿することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/25f9b547-34ed-0361-46af-5d70cc61b8c6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/459a8c80-8a11-de2c-0c24-52e4c1a7ab9c.png)


投稿すると投稿ゆるケア一覧に追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/ea8d786e-8903-d766-90f6-15f9b9024af9.png)

機能をざっくりまとめると、できることとしては

- ゆるケアの投稿
- ゆるケアの閲覧、スキ、リスト追加

といった形になります。

## firestore設計

仕様をなんとなく理解したところで設計に落とし込んでみます。

全体像としては下記になります。

- circles
    - cares
        - likers
- users
    - notifications
    - saveCares
    - actionCares
    - deviceTokens
- personalData

### 共通のお約束

Mapの型として共通で用いる型は下記になります。

*ImageInfo*
画像の情報を保存しています。パスだけ保管しているのでドメインなどはクライアント側でつなげて画像を読み込みます。
また、width/height情報を持つので、ロードする前のレイアウト調整にも使うことができます。
|property|type|description|
|-|-|-|
|path|String|画像の保存パス|
|width|Number|横サイズ|
|height|Number|縦サイズ|

また、各ドキュメントにはcreatedAt,updatedAtはすべてつけるものとします。

### circles

サークル情報をまとめたものです。
ID: サークル名（Stretch, GoodEvening,,,）

|property|type|description|
|-|-|-|
|circleName|String|サークル情報|
|careCount|Number|ゆるケア数|
|ownerName|String|サークルの作成者|
|ownerImage|ImageInfo|サークル作成者の画像情報|

## circles/{circleId}/cares

ゆるケアを扱います。
人気ケアやおすすめとかではGroupCollectionを使って網羅的に読み込みます。

ID: 自動生成

|property|type|description|
|-|-|-|
|circleId|String|サークルID。Referenceのpathから取れなくもないですが、扱いづらいのでドキュメントにも入れます。|
|username|String|ゆるケア作成者|
|userImage|ImageInfo|ゆるケア作成者の画像情報|
|userId|String|ゆるケア作成者のuserId|
|categories|Array(String)|カテゴリ情報一覧|
|likeCount|Number|スキ総数|
|saveCount|Number|リスト総数|
|actionCount|Number|実施総数|
|careTitle|String|ゆるケアのタイトル|
|careDescription|String|ゆるケアの内容|
|hashTags|Array(String)|ハッシュタグの一覧|
|careImage|ImageInfo|ゆる画の画像情報|


createのCloudFunctionsで下記を実施します
- circle.careCountのインクリメント
- user.careCountのインクリメント

## circles/{circleId}/cares/{careId}/likers

ゆるケアに対するスキを扱います。
ID: userId

|property|type|description|
|-|-|-|
|username|String|いいねしたユーザ名|
|userImage|ImageInfo|いいねしたユーザ画像情報|
|toUserId|String|いいねしたゆるケア作成者のuserId|

createのCloudFunctionsで下記を実施します。
- care.likeCountのインクリメント
- toUserId先のuser.likeCountのインクリメント
- toUserId先のuser.notificationのドキュメント追加
- toUserId先のuserにpush通知

## users

ユーザ情報を扱います
ID: firebase authenticationで用いるuserId

|property|type|description|
|-|-|-|
|username|String|ユーザ名|
|userImage|ImageInfo|ユーザの画像情報|
|careCount|Number|ゆるケア投稿数|
|likeCount|Number|スキされた総数|
|careImage|ImageInfo|ゆる画の画像情報|


### users/{userId}/notifications

通知周りを扱います
ID: 自動生成

|property|type|description|
|-|-|-|
|notificationType|String|アクションごとに定義（save, action, like）|
|notificationDescription|String?|通知内容|
|careReference|DocumentReference?|遷移先のゆるケア参照先|

### users/{userId}/saveCares

ユーザがリストに追加したゆるケア一覧。
ID: 自動生成

|property|type|description|
|-|-|-|
|careReference|DocumentReference|遷移先のゆるケア参照先|
|careTitle|String|ゆるケアのタイトル|
|username|String|ゆるケア作成者|
|userId|String|ゆるケア作成者のuserId|
|categories|Array(String)|カテゴリ情報一覧|
|careImage|ImageInfo|ゆる画の画像情報|

### users/{userId}/actionCares

実施したゆるケア一覧を保存します。
ID: 自動生成
|property|type|description|
|-|-|-|
|careReference|DocumentReference|遷移先のゆるケア参照先|
|careTitle|String|ゆるケアのタイトル|
|userId|String|ゆるケア作成者のuserId|
|categories|Array(String)|カテゴリ情報一覧|
|reaction|String|やってみた結果の反応（satisfy, enjoy, etc...）|

### deviceTokens

push通知用のdevice tokenを登録します。
ID: userId

|property|type|description|
|-|-|-|
|userId|String|ユーザID|
|fcmToken|Array(String)|通知に使うfcmToken一覧|

### personalData

個人情報を扱います。
ID: userId
|property|type|description|
|-|-|-|
|gender|String|性別 male, female, unknown|
|birthday|Timestamp|誕生日|
|hobby|Array(String)|趣味・興味|

## ヒットした要因

心も体も癒やしたいと思う現代人が多いというところにアプリがフィットしたのではないかと思います。
ケアとしても気軽にできるものがおおく、やってみたら良かったという人が連鎖的に増えていってるのかなと思いました。

## まとめ

シンプルな作りなため設計もしやすいアプリでした。
逆に言うと今後の伸び代もあるとおもうので今後の発展を楽しみにしております。

最後に、[ワンナイト人狼オンライン](https://online.1nite-jinro.com/link/blog)というゲームを作ってます！よかったら遊んでね！

https://online.1nite-jinro.com/link/blog

他にも[Camecon](https://camecon.me/)や[Offcha](https://offcha.com/)といったサービスも作ってるのでよかったら使ってね！

https://camecon.me/

https://offcha.com/

また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。

https://virapture.com/