Cloud Firestoreについてまとめる

#はじめに
備忘録として、Firebase Cloud Firestore(以下、Firestore)についてまとめていきます。

そもそもFirebaseが何なのか？というのは今回は割愛します。

#Firestoreを知る前に
データベースには大きく分類すると、`RDBMS`と`NoSQL`に分けることができ、前者は`SQL`というコンピューター言語を使用して、データの書き込み・読み取りを行います。

対して、後者の`NoSQL`は文字通り、`SQL言語を使用せずにデータの書き込み・読み取りを行っています`。

主な違いは管理方法にあり、RDBMSは`1つのキーに対して複数の付随するデータを管理`しているのに対し、NoSQLは`1つのキーに対して1つの付随するデータを管理`しています。

・RDBMS 「1キー：複数の付随データ」

・NoSQL 「1キー：1つの付随データ」

Firestoreでは`NoSQLでデータが管理`されており、`クラウドデータベース`になっています。

#クラウドデータベースとは
`手元にサーバーやソフト等の環境を持たずにデータベースを利用することができるサービス`の事です。

これはデータベースに限った話ではなく、手元にサーバーやソフトなどの環境がなくても利用できるサービスは`クラウドサービス`としてまとめられます。

この主な例として他にも`Gmail`や`iCloud`などがあり、`Firebase`も該当します。

どれも利用する側は環境構築を1からしなくても、インターネットに繋がっていればサービスを利用することが出来ます。

#Firestoreとは
Googleが提供している`NoSQLクラウドデータベース`です。
[Cloud Firestore | Firebase](https://firebase.google.com/docs/firestore?hl=ja)

公式ドキュメントを見てもらうと分かるようにFirestoreでは`コレクション`、`ドキュメント`等の用語が登場します。

###・ドキュメント
`あらゆるデータを長期間保存する場所`です。

例えば、`humanドキュメント`が作られた場合は下記のようになります。

```
📄human(ドキュメント)
   first(フィールド): "Larry"(値)
   last: "Page"
   born: 1973
```

各ドキュメントには`キー(フィールド)`と`値`のペアが含まれており、`ドキュメントID`で識別されています。

ドキュメントIDは`重複`せず、通常は追加と同時にランダムなIDが付与され、ユーザーIDなどの`独自のキー等を自分で指定することも可能`です。

更に、ドキュメント内のデータを`マップ(ドキュメント内で複雑にネストされたオブジェクト)で構造化`することも出来ます。

```
📄human
   name:
     first: "Larry"
     last: "Page"
   born: 1973
```
ドキュメントは`JSON`に似ており、公式もJSONと`基本的には同じ`と公言しています。

###・コレクション
`複数のドキュメントをまとめるフォルダみたいなもの`です。

仕組みとしては`データをドキュメントに書き込み、そのドキュメントをコレクションにまとめる`といった感じです。

公式ドキュメントの以下の画像がわかりやすいと思います。
![firestoreImage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/ffa08b0c-0b22-00e1-11f8-2f187267744b.png)
(出典: [Cloud Firestore データモデル | Firebase](https://firebase.google.com/docs/firestore/data-model?hl=ja))

例えば、`foodコレクション`を作成して、様々な食べ物を表すドキュメントを格納した場合このようになります。

```
🗂food(コレクション)
  📄meet(ドキュメント)
     kind(フィールド): "ChickenMeat"(文字列型の値)
     Id: 12345678(数値型の値)
  📄fruit
     kind: "Apple"
     Id: 87654321
```
Firestoreでは、Bool値、数値、文字列、タイムスタンプなど、様々なデータ型の値がサポートされています。

コレクションは、自分から`作成・削除をする必要がなく`、最初のドキュメントを追加した時に勝手に作られ、コレクション内のドキュメントを全て削除すると自動的にコレクションも削除されます。

そして、コレクションには`ドキュメントのみしか含めることができません`。なので、コレクションに対して`生のフィールド`や`他のコレクションを含める`ことは許されていません。

###・リファレンス
`データベース内の場所を参照するだけの軽量なオブジェクト`です。

先ほどのfoodコレクション内のドキュメントを参照してみましょう。

```
🗂food
  📄meet
     kind: "ChickenMeat"
     Id: 12345678
  📄fruit
     kind: "Apple"
     Id: 87654321
```

```swift
let foodDocumentRef = Firestore.firestore().collection("food").document("meet")
```
これで、コレクション内のドキュメントを参照することが出来ます。

もちろん、コレクションへのリファレンスも作成可能です。

```swift
let foodDocumentRef = Firestore.firestore().collection("food")
```

`コレクションリファレンス`と`ドキュメントリファレンス`は`2種類の異なるもの`であり、それぞれ別の操作が可能です。

例えば、コレクションリファレンスを使用して`コレクション内のドキュメントに対するクエリを実行`したり、ドキュメントリファレンスを使用して`個々のドキュメントを読み書き`したりできます。

ドキュメントまたはコレクションへのパスを文字列として指定し、`スラッシュ（/）`で区切ってリファレンスを作成することもできます。

```swift
let meetDocumentRef = Firestore.firestore().document("food/meet")
```

###・サブコレクション

例えば、メッセージとチャットルームを使ったチャットアプリがあったとします。

下記のようなroomsコレクションがあって、ここに`メッセージを保存する場所`を指定しなくてはいけません。ですが、Firestoreのドキュメントは`軽量`にする必要があり、膨大な数のメッセージを格納するのは厳しいようになっています。

```
🗂rooms
  📄roomA
     name: "my Room"
  📄roomB
     name: "dog talk"
.
.
.
```

そういう場合には`サブコレクション`を使用します。
これは、`特定のドキュメントに関連付けられたコレクション`です。

roomsコレクション内の全てのルームドキュメントに`messageサブコレクション`を作成してみましょう。

```
🗂rooms
  📄roomA
     name: "my Room"
       🗂message(サブコレクション)
          📄message1(ドキュメント)
             from: "taka"
             msg: "Hello World!"
          📄messsage2
             from: "rio"
             msg: "Hi!"

  📄roomB
.
.
.            
```
次のコードを使用してサブコレクション内のメッセージへの`リファレンス`も作成可能です。

```swift
let messageRef = Firestore.firestore()
      .collection("rooms").document("roomA")
      .collection("message").document("message1")
```

更に`サブコレクション内のドキュメントもサブコレクションを格納`できるため、深くネストできます。最大`100レベル`までネスト可能です。

しかし、注意すべき点が2つあります。

#####①コレクションとドキュメントが常に交互になるようにしなくてはいけない
なので、コレクション内のコレクションやドキュメント内のドキュメントは`参照できません`。

#####②ドキュメントを削除しても、その中のサブコレクションは削除できない
例えば、親ドキュメントを削除する時にサブコレクション内のドキュメントも削除する場合は[手動で削除](https://firebase.google.com/docs/firestore/manage-data/delete-data?hl=ja#collections)する必要があります。

#おわりに
Firestoreについてまとめました。

今回よく分かったことは困ったら公式ドキュメントを見た方が良いという事です。

次は、Firestoreのセキュリティルールについてまとめようと思います。