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();
})()