FirestoreでBatch処理


FirestoreではTransaction処理が可能ですが、件数が多い場合はBatch処理を使うほうがいいみたいです。
が、Batch処理には500件以上を一度に処理できないとう制限があるので、その検証と回避方法についてテストしてみます。

準備・前提

  • membersコレクションを作成して500件以上のデータを作成しておく。
  • membersコレクションにはstatusフィールドがあり、基本falseになっている。
  • ローカルで実行するnodeスクリプトを想定。

コード1(500件対応なし)

statusがfalseになっているのをtrueにするバッチ。

const admin = require('firebase-admin');

admin.initializeApp({
    credential: admin.credential.cert('/path/to/key.json'),
    databaseURL: 'https://xxxxxxxxxx.firebase.com',
});

const db = admin.firestore();
//batchインスタンス生成
let batch = db.batch();

(async () => {

    //collectionからデーを取得
    const snapshots = await db.collection("members").get();
    //ループしながら・・・
    const docs = snapshots.docs.map((doc, index) => {

        //update
        batch.update(doc.ref, { status: false })
    });

    //最終commit
    batch.commit();

})()

これを実行すると、

Error: 3 INVALID_ARGUMENT: maximum 500 writes allowed per request

というエラーになる。

コード2(500件対応あり)

500件毎にcommit()を実行して500件制限を回避します。

const admin = require('firebase-admin');

admin.initializeApp({
    credential: admin.credential.cert('/path/to/key.json'),
    databaseURL: 'https://xxxxxxxxxx.firebase.com',
});

const db = admin.firestore();
//batchインスタンス生成
let batch = db.batch();

(async () => {

    //collectionからデーを取得
    const snapshots = await db.collection("members").get();
    //ループしながら・・・
    const docs = snapshots.docs.map((doc, index) => {

+        //500件毎にcommitしてbatchインスタンスを初期化
+        if ((index + 1) % 500 === 0) {
+            batch.commit(); //新しいインスタンス
+            batch = db.batch(); //新たにインスタンスを生成。
+        }

        //update
        batch.update(doc.ref, { status: false })
    });

    //最終commit
    batch.commit();

})()