Firebase Cloud Firestoreの備忘録

Cloud Firestoreの備忘録です。

[公式ドキュメント](https://firebase.google.com/docs/reference/node/firebase.firestore)

## よく使うAPI

使い方は以下の記事が分かりやすかったです。

[Firebase Cloud Firestoreの使い方 - Qiita](https://qiita.com/subaru44k/items/a88e638333b8d5cc29f2)

### CollectionReference

[CollectionReference \| JavaScript SDK  |  Firebase](https://firebase.google.com/docs/reference/node/firebase.firestore.CollectionReference)

``` typescript
const collectionRef: firebase.firestore.CollectionReference = firebase.firestore().collection("cities");
```

よく使うメソッド

- get(): QuerySnapshotを返す
- doc(): 指定されたパスのDocumentReferenceを取得
- where():  条件を絞り込み
- onSnapshot(observer: object): コレクションに変更があった場合にobserverを実行。

### DocumentReference

[DocumentReference \| JavaScript SDK  |  Firebase](https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference)

``` typescript
const docRef: firebase.firestore.DocumentReference = firebase.firestore().collection("cities").doc("SF");
```

よく使うメソッド

- get(): ドキュメントを取得
- set(): ドキュメントを新規作成
- update(): ドキュメントを更新
- collection(): 指定されたパスのCollectionReferenceを取得

collection -> doc -> collection -> doc ... と参照することができます。

### QuerySnapshot

[QuerySnapshot \| JavaScript SDK  |  Firebase](https://firebase.google.com/docs/reference/node/firebase.firestore.QuerySnapshot.html)

> QuerySnapshotには、クエリの結果を表す0個以上のDocumentSnapshotオブジェクトが含まれます。 ドキュメントは、docsプロパティを介して配列としてアクセスするか、forEachメソッドを使用して列挙できます。 ドキュメントの数は、空およびサイズのプロパティを介して決定できます。

``` typescript
// 全ドキュメントのスナップショット
const querySnapshot = await collectionRef.get();
// populationが100より小さい全ドキュメントのスナップショット
const querySnapshot = await collectionRef.where("population", "<", 100).get();
```

よく使うメソッド

- forEach(): QuerySnapshot内のすべてのドキュメントを列挙。

### DocumentSnapshot

[DocumentSnapshot \| JavaScript SDK  |  Firebase](https://firebase.google.com/docs/reference/node/firebase.firestore.DocumentSnapshot.html#data)

> DocumentSnapshotには、Firestoreデータベース内のドキュメントから読み取られたデータが含まれます。.data（）または.get（）を使用してデータを抽出し、特定のフィールドを取得できます。

- data(): フィールドを取得。

## 初期化前に実行するとエラー

`Uncaught FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).`

Vueの場合、main.tsで初期化される前にコンポーネントファイル内でDBにアクセスしようとすると怒られます。

```
import firebase from 'firebase';
const db = firebase.firestore(); 

export default Vue.extend({
...
});
```

## QuerySnapshot forEach

[DataSnapshot forEach](https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot.html#foreach)

> JavaScriptオブジェクトの動作方法により、によって返されるJavaScriptオブジェクト内のデータval()の順序は、サーバー上の順序やchild_addedイベントの順序と一致するとは限りません。それは forEach()便利です。これにより、DataSnapshot クエリの順序でaの子が反復されることが保証されます。

[Array.prototype.forEach()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)ではないので注意。

docsで配列にアクセスしてArray.prototype.forEach()を使うことも可能。

```
// QuerySnapshot forEachを使った場合
querySnapshot.forEach((doc) => {
  console.log(doc.data());
});
// Array.prototype.forEach()を使った場合
querySnapshot.docs.forEach((doc) => {
  console.log(doc.data());
});
```

基本的には[DataSnapshot forEach](https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot.html#foreach)を使うべきです。

## The query requires an index...

![スクリーンショット 2019-11-29 18.39.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510204/ffd334e7-7180-5b19-6bee-cc8e0d2153b6.png)

consoleにThe query requires an indexというエラーがでた場合はコンソールのリンクをクリックすれば自動でインデックスを生成してくれます。自分で生成するよりキー名のミスなどが発生しないので間違いないでしょう。



## 設計関連

[Cloud Firestoreの勘所 パート2 — データ設計 - google-cloud-jp - Medium](https://medium.com/google-cloud-jp/firestore2-920ac799345c)

[Firebase入門 フリマアプリを作りながら、認証・Firestore・Cloud Functionsの使い方を学ぼう！ - エンジニアHub｜若手Webエンジニアのキャリアを考える！](https://employment.en-japan.com/engineerhub/entry/2019/06/07/103000#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%92%E9%80%9A%E3%81%97%E3%81%A6Firebase%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E9%96%8B%E7%99%BA%E3%82%92%E5%AD%A6%E3%81%B6)