Firestoreコレクションの全データ件数を取得する方法

#Firestore: 全データ件数を取得する方法

ページネーションで必要な、Firestoreコレクションの全データ件数取得。データサイズによって取得方法を変えた方がよい（パフォーマンスに影響）。

以下に方法。

##数百件程度の場合
データをローカルにロードしてカウントする。

```typescript
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { Observable } from 'rxjs';

  constructor(
    private db: AngularFirestore,
  ) {}

  ngOnInit() {
  }

  length: number; // 全件数を格納する変数

  // commentsコレクションの全データ件数を獲得しlengthに保存
  getDataSize() {
    this.db.collection('comments').valueChanges().subscribe( values => {
      console.log('■データ数は、' + values.length);
      this.length = values.length
    })
  }
```

そしてこの関数をngOnInit() {..}に突っ込んでおけばいい。

```typescript
  ngOnInit() {
    this.getDataSize();
  }
```


##数千件の場合
Cloud Functionsを利用してそちらでカウントさせる。

Functionsの利用の仕方は[こちら](https://qiita.com/atomyah/items/4c7784a09ef215f256aa#firebase-function%E3%81%AE%E8%A8%AD%E5%AE%9A)で。

#####functions/src/index.tsを編集

コードは以下の通り。

```typescript

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as rp from 'request-promise';
// firebase の初期化
admin.initializeApp(functions.config().firebase) 

const fireStore = admin.firestore()

// commentsコレクションのデータ数カウント
exports.countComments = functions.https.onRequest((req, res) => {
  let commentsfaqsRef = fireStore.collection('commentsfaqs');
  commentsfaqsRef.get().then( snap => {
    res.header('Access-Control-Allow-Origin', "*");
    res.header('Access-Control-Allow-Headers', "Origin, X-Requested-With, Content-Type, Accept");
    res.status(200).send({length: snap.size});
  })
  .catch(error => {
      res.send( error() );
  });
});
```

res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Headers', "Origin, X-Requested-With, Content-Type, Accept");
の2行をつけないとCORS関連のエラーがでる。
こんな感じのエラーメッセージ↓

```bash
Access to fetch at 'https://<your-project>.cloudfunctions.net/<your-function>' 
from origin 'http://localhost:3000' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
If an opaque response serves your needs, 
set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
```

#####firebase deploy
そうしたら該当ファンクションだけデプロイする。

```bash
$ firebase deploy --only functions:countComments
```

以下のようにcountCommentsファンクションだけデプロイされ、完了前にFunction URLが表示されるので控えておく。

```bash
…略…
i  functions: uploading functions in project: countComments(us-central1)
i  functions: creating Node.js 8 function countComments(us-central1)...
+  functions[countComments(us-central1)]: Successful create operation.

Function URL (countComments): https://us-central1-projectName.cloudfunctions.net/countComments

 Deploy complete!
```

ためしにそのURLにアクセスすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/8298a06d-a1aa-7c92-311b-41e2b81bce9a.png)
カウントされたデータ件数が表示されている。

#####クライアント側でRESTクライアントを実装する
あとはcountCommentsが吐き出したデータ件数をクライアント側（Angular)でフェッチするだけ。HttpClientModuleを使う。

- app.module.tsにHttpClientModuleをインポート

```typescript
import { HttpClientModule } from '@angular/common/http';

  imports: [
    HttpClientModule,
  ]
```

- データ件数を利用したいコンポーネントに関数を作る

```typescript
import { HttpClient } from '@angular/common/http';

  constructor(
    private httpClient: HttpClient,
  ) {}

  ngOnInit() {
    this.getDataSize();
  }

  countCommentsURL : string = 'https://us-central1-projectName.cloudfunctions.net/countComments' // function 'countComments'のURL
  length: number; // 全件数を格納する変数

  // commentsコレクションの全データ件数を獲得しlengthに保存
  async getDataSize() {
     this.httpClient.get(this.countCommentsURL)
      .toPromise()
      .then((res) => {
        const response: any = res;
        this.length = response.length
      })
      .catch((error) =>
        console.log(error)
      );
  }
```


##一万件以上の場合

To Be Continue…

<br>

参考：
[[Angular] HTTPクライアント(RESTクライアント)を実装する](https://qiita.com/ksh-fthr/items/840ae54472892a87f48d)
[FirebaseのCloud FunctionsでCORSが~とかAccess-Control-Allow-Originが~と言われたらこれ](https://qiita.com/qrusadorz/items/40234ac0b5c5c2315cad)
[Google Cloud Functionsでcorsを有効にする](https://aknow2.hatenablog.com/entry/2018/09/11/165107)