GCPのCloud FirestoreのネイティブモードとDatastoreモードの違い

# はじめに
GCPのCloud Firestore Datastoreモードを使用してサーバレスのWebサービスPocを実現しました。
その際に、FirebaseのCloud FirestoreとGCPのCloud Firestoreがネットで情報が混在していた為、その部分についてまとめてみました。
何か間違っている場合、また意見があれば募集中です:innocent:

# :orange_book: Cloud Firestoreの概要
GCPのCloud Firestoreは2019年2月1日に正式リリースされた、FirebaseとGCPからのモバイル、Web、サーバー開発に対応した柔軟でスケーラブルな NoSQL クラウド データベースです。
まとめると、Firebase の技術をベースにして、Google Cloud Platform に統合されたサービスです。
Cloud Firestoreには2種類のネイティブモードとDatastoreモードの二種類があり、どちらか一方しか選ぶことしかできません。

## :pushpin: Datastoreモード
DatastoreモードのCloud Firestoreは2013年5月にリリースされていたCloud Datastoreの次世代サービスとしての位置づけとなっていた。現在はGCPのCloud Firestoreが正式リリースされてCloud Firestoreとして[自動アップグレード](https://cloud.google.com/datastore/docs/upgrade-to-firestore?hl=ja)できるようになっています。 
Firestoreのストレージレイヤにアクセスできるようになったため、Cloud Datastoreでは窮屈に感じた下記の制限がなりました。

- 結果整合性の制限がなくなり、Cloud Datastoreクエリすべてで強整合性を確保できます。
- 25 エンティティ グループまでというトランザクションの制限がなくなった
- 1 秒あたり 1 個というエンティティ グループへの書き込み制限がなくなった。

ただ、Cloud Datastoreのシステム動作を使用するため互換性のないCloud Firestoreの下記機能が無効になります。

- プロジェクトは Cloud Datastore API リクエストを受け入れ、Cloud Firestore API リクエストを拒否します。  
- プロジェクトでは、Cloud Firestore インデックスの代わりに Cloud Datastore インデックスが使用されます。  
- そのプロジェクトでは Cloud Datastore クライアント ライブラリを使用できますが、Cloud Firestore クライアント ライブラリは使用できません。  
- Cloud Firestore のリアルタイム機能は利用できません。
- GCP Console でのデータベース閲覧には Cloud Datastore Viewer を使用します。

## :pushpin: ネイティブ モード
Cloud Datastore と Firebase Realtime Database を最大限に活用し、自動スケーリングと高パフォーマンスを実現し、アプリケーション開発をより快適にするように構築された NoSQL ドキュメント データベースです。
上記の説明のようにFirebaseのCloud FirestoreをGCPでも使用できるようになった。
以下、追加された新機能

- 新しい強整合性に優れたストレージ レイヤ
- コレクションとドキュメントのデータモデル
- リアルタイム アップデート
- モバイル クライアント ライブラリとウェブ クライアント ライブラリ

## :green_book: ネイティブモードとDatastoreモードの機能比較
||Cloud Firestore<br>ネイティブ モード|Cloud Firestore<br>Datastore モード|
|:--|:--|:---|:--|:--|  
|<b>データモデル</b>|ドキュメントとコレクションに分類されたドキュメント データベース|種類とエンティティのグループに分類されたエンティティ|
|<b>ストレージ レイヤ</b>|常に強整合性のある新たなストレージ レイヤ|常に強整合性のある新たなストレージ レイヤ|
|<b>[Cloud Datastore v1 API](https://cloud.google.com/datastore/docs/reference/data/rest/?hl=ja)のサポート</b>|なし。リクエストが拒否される|あり|
|<b>[Cloud Firestore v1 API ](https://cloud.google.com/firestore/docs/reference/rest/?hl=ja)のサポート</b>|あり|なし。リクエストが拒否される|
|<b>リアルタイム アップデート</b>|[リアルタイム更新のための、ドキュメントまたは一連のドキュメントをリッスンする機能をサポート](https://cloud.google.com/firestore/docs/query-data/listen?hl=ja)<br>ドキュメントまたは一連のドキュメントをリッスンしながら、クライアントにデータの変更を通知し、最新のデータセットを送信|サポート対象外|
|<b>オフライン データの永続性</b>|[モバイルクライアントライブラリとウェブクライアントライブラリでオフラインデータの永続性をサポート](https://cloud.google.com/firestore/docs/manage-data/enable-offline?hl=ja)|サポート対象外|
|<b>クライアント ライブラリ</b>|Cloud Firestore クライアント ライブラリ:<br>・Java<br>・Python<br>・PHP<br>・Go<br>・Ruby<br>・C#<br>・Node.js<br>・Android<br>・iOS<br>・ウェブ<br>|Cloud Datastoreクライアントライブラリ:<br>・Java<br>・Python<br>・PHP<br>・Go<br>・Ruby<br>・C#<br>・Node.js|
|<b>セキュリティ</b>|・Cloud Identity and Access Management（IAM）でデータベース アクセスを管理<br>・Cloud Firestore のセキュリティ ルールは、モバイルおよびウェブ クライアント ライブラリのサーバーレス認証および承認をサポート|Cloud Identity and Access Management（IAM）でデータベース アクセスを管理|
|<b>パフォーマンス</b>|数百万のクライアント同時実行まで自動的にスケーリング。1 秒あたり最大 10,000 件の書き込み|毎秒数百万回の書き込みまで自動的にスケーリング|
|<b>SLA</b>|[Cloud Firestore SLA](https://cloud.google.com/firestore/sla?hl=ja)|[Cloud Firestore SLA](https://cloud.google.com/firestore/sla?hl=ja)|
|<b>ロケーション</b>|同じロケーション|
|<b>料金</b>|同じ料金体系|
|<b>Console</b>|Firebase コンソールおよび GCP Console Firestore Viewer|GCP Console Datastore Viewer|
|<b>名前空間</b>|サポート対象外|名前空間に対応|
|<b>App Engine クライアント ライブラリの統合</b>|App Engine スタンダード環境の Python 2.7 および PHP 5.5 ランタイムではサポートされない<br>App Engine スタンダード環境の Python 3.7、PHP 7.2、Java 8、Go、Node.js のランタイムでサポート<br>App Engine フレキシブル環境のすべてのランタイムでサポート|すべてのランタイムでサポート|

引用：[ネイティブ モードと Datastore モードからの選択](https://cloud.google.com/firestore/docs/firestore-or-datastore?hl=ja#feature_comparison)

機能比較で注目する点は以下の4点
1. Console
2. APIサポート
3. リアルタイムアップデート
4. オフライン データの永続性

### 1.Consoleの比較
ネイティブモードは`Firebase コンソールおよび GCP Console Firestore Viewer`と記載されていて、Faibaseのコンソール画面とGCPのコンソール画面の両方で管理ができることがあかります。
FirebaseコンソールとGCP Consoleのどちらで開始するかは公式ドキュメントで以下の様に使い分けています。

- Firebaseコンソールの場合  
[モバイル / ウェブ クライアント ライブラリの使用](https://cloud.google.com/firestore/docs/quickstart-mobile-web?hl=ja)
- GCP Consoleの場合  
[サーバー クライアント ライブラリの使用](https://cloud.google.com/firestore/docs/quickstart-servers?hl=ja)

### 2.APIサポートの比較
ネイティブモードとDatastoreモードはそれぞれ異なるAPIのサポートとなっています。 
ネイティブモードはFirebaseのCloud Firestoreベースとなっていて、DatastoreモードはCloud Datastoreがベースになっているためです。

###3.リアルタイムアップデートの比較
Datastoreモードはサポートされていませんが、ネイティブモードはクライアントにデータの変更を通知し最新のデータセットを送信できる為、更新されたドキュメントをリッスンする機能がサポートされています。

### 4.オフライン データの永続性の比較
Datastoreモードはサポートされていませんが、ネイティブモードではキャッシュに保持することでき、オフラインでも書き込み、読み取り、リッスン、クエリができます。オンラインに戻ると、アプリがローカルで行った変更と Cloud Firestore バックエンドが同期されます。 
※この機能は、Android、iOS、ウェブアプリのみでサポートされている。

# 最後に
まとめとして、GCPのCloud FireStoreはFirebaseのFireStoreをGCPのCloud Datastoreと統合されたサービスです。
また、一つのプロジェクトでネイティブモードとDatastoreモードを一緒に使うことができないため使える機能などを考えて選択する必要があります。 
ネイティブモードのみCloud Firestore APIを使用できますが、クライアントライブラリもネイティブモードとDatastoreモードで使用できるライブラリは違います。ですので、当たり前ですが公式ドキュメントをちゃんと読むことが大切だと感じました。

## 参考資料
[Cloud Firestore ドキュメント](https://cloud.google.com/firestore/docs/concepts?hl=ja)
[Datastoreモードの Cloud Firestore APIとリファレンス](https://cloud.google.com/firestore/docs/?hl=ja)
[ネイティブモードのCloud Firestore API とサーバー クライアント ライブラリのリファレンス](https://cloud.google.com/firestore/docs/apis?hl=ja)