FireStore一括書き込み500件超エラー(batch処理)

2019-09-23

firestoreでは一括書き込み(バッチ処理)ができる。公式によると複数データの書き込み、更新、削除を行う時、batch処理した方が良いとされている。

一括オペレーションとともに使うことで接続のオーバーヘッドが軽減され、データ移行をより迅速に行うことができます。 FireStore 一括書き込み

どんな時にFireStoreでバッチ処理する?

例えば以下のようにhogeコレクションから全てのドキュメントを取得してフラグをtrueに書き換える場合。

	const batch = db.batch();
	db.collection('hoge').get()
        .then(snapshot => {
            snapshot.forEach(doc => {
               batch.update(doc.ref, {flg: true});
            });
        });
    return batch.commit();

batch.commit()はPromiseを返すので場合によってはawaitすれば良い。

一括処理は500件まで

バッチ処理件数が500件を超える場合、FireStoreがエラーを吐く。

Error: 3 INVALID_ARGUMENT: maximum 500 writes allowed per request

確かに公式でも最大 500 のオペレーションまでとある。
500件を終えるドキュメントを一括で処理したい場合は以下のようにすれば良いのか。

	let batch = db.batch();
	db.collection('hoge').get()
        .then(snapshot => {
        	let cnt = 0;
            snapshot.forEach(doc => {
               cnt++
               if (cnt > 500) {
                   batch.commit();
                   batch = db.batch();
               }
               batch.update(doc.ref, {flg: true});
            });
        });
    return batch.commit();

これbatch.commitの結果を待たずに次のbatch処理を初めちゃってるけど、いずれにせよbatch.commitが複数に渡るので、トランザクション処理はしなければいけない。

そうするとバッチ処理とトランザクション処理が併用できなければいけないが公式にはそのような記述はないように思われる。

500件を超えるバッチ処理を行いたいケースって、リアルタイム性は求められない処理だと思われ。なので応答速度は無視してトランザクションを作成し1件ずつ書き込んだ方が良いと感じる。
一方、500件以内の書き込みだということがあらかじめわかっていて、全て同一の処理を行う場合は一括書き込み(batch処理)で行うべきなのか。