Firestoreでコレクションを削除する


Firestoreではコレクションを一発削除するコマンドが存在しない。。。
[本家サイト](https://firebase.google.com/docs/firestore/manage-data/delete-data?hl=ja)を参考に削除できるかしてみた。

## 準備

membersというコレクションに1800件のデータを生成。
なぜ1800件かというと、サンプルはbatch処理を使っていて、batch処理の上限が500件なのでうまく動作するか見るため（そういういみでは501件でもよい）。

とりあえずfirebase-adminを利用したローカルのnode.jsスクリプトとして実装した。

```js:createMembers.js
const admin = require('firebase-admin');
admin.initializeApp({
    credential: admin.credential.cert("/path/to/key.json"),
    databaseURL: 'https://xxxxxxxxxx.firebaseio.com',
});
const db = admin.firestore();

for (let i = 0; i < 1800; i++) {

    db.collection("members").add({
        id: i,
        name: 'hoge',
    });

}
```

## 削除を試す

ほぼ本家サイトのコードのまま。

```js:deleteCollection.js
const admin = require('firebase-admin');
admin.initializeApp({
    credential: admin.credential.cert("/path/to/key.json"),
    databaseURL: 'https://xxxxxxxxxx.firebaseio.com',
});
const db = admin.firestore();


//firebaseのサイトにあるコード（少し改修）
const deleteCollection = (db, collectionRef, batchSize) => {
    const query = collectionRef.orderBy('__name__').limit(batchSize);
    return new Promise((resolve, reject) => {
        deleteQueryBatch(db, query, batchSize, resolve, reject);
    });
}

//削除のメインコード
const deleteQueryBatch = (db, query, batchSize, resolve, reject) => {
    query.get()
        .then((snapshot) => {
			
			 //検索結果が0件なら処理終わり
            if (snapshot.size == 0) {
                return 0;
            }
            
			 //削除のメイン処理
            const batch = db.batch();
            snapshot.docs.forEach(doc => {
                batch.delete(doc.ref);
            });
			
			 //一旦処理サイズをreturn
            return batch.commit().then(() => {
                return snapshot.size;
            })
        })
        .then((numDeleted) => {
			  
			 //もう対象のデータが0なら処理終わり
            if (numDeleted == 0) {
                resolve();
                return;
            }
			 
			 //あだあるなら、再度処理
            process.nextTick(() => {
                deleteQueryBatch(db, query, batchSize, resolve, reject);
            });
        })
        .catch(reject);
}

//実行
const colRef = db.collection("members");
deleteCollection(db, colRef, 500);
```

## おまけ

firebaseコマンドでも消せると書いてあるが、どう書けばいいかわからなかったので試してみた。
いちおう下記のようにしたら消えた。

```bash
firebase firestore:delete members -r --project [project_id]
```

>私はfirebase initしてない場所で試したのでプロジェクトIDを聞かれたけどinitしてればいらないかも。

なお、オプションは下記のような感じ。

```bash
firebase firestore:delete -h       

  -r, --recursive    Recursive. Delete all documents and subcollections. Any action which would result in the deletion of child documents will fail if this argument is not 
                     passed. May not be passed along with --shallow.
  --shallow          Shallow. Delete only parent documents and ignore documents in subcollections. Any action which would orphan documents will fail if this argument is not 
                     passed. May not be passed along with -r.
  --all-collections  Delete all. Deletes the entire Firestore database, including all collections and documents. Any other flags or arguments will be ignored.
  -y, --yes          No confirmation. Otherwise, a confirmation prompt will appear.
  -h, --help         output usage information
```

firebase firestore:delete --all-collectionsという危険なものもある。