AIイノベーションズ

Firestoreのドキュメントを一括で処理するバッチ処理コード

Firestoreのドキュメントを一括で処理するバッチ処理コードを紹介。バッチ処理は一度に最大500件のドキュメント更新を許可します。

フィールド created_at の順番に処理をしていきます。

const admin = require('firebase-admin');
 
const firebaseApp= initializeApp({
  credential: cert(serviceAccount),
  databaseURL: "https://foo.firebaseio.com"
}, "firebaseApp");
const db = getFirestore(firebaseApp)
 
/**
 * Firestore コレクションのドキュメントをバッチ処理で更新します。
 * Firestore のバッチ書き込みは一度に最大 500 件のドキュメント更新を許可します。この関数は、500 件を超えるドキュメントをシーケンシャルに処理することで対応します。
 *
 * @param {string} collectionName - 更新する Firestore コレクションの名前。
 * @param {Object} updatingFieldAndValue - 各ドキュメントで更新するフィールドについて、キーと値のペアのオブジェクトとして指定。
 * @param {number} [batchSize=500] - 各バッチで更新する最大ドキュメント数。デフォルトは 500。
 * @returns {Promise<void>} - すべてのバッチが処理されたときに解決する Promise。
 * @throws Firestore 操作に問題が発生した場合にエラーをスローします。
 */
async function updateDocumentsInBatches(collectionName, updatingFieldAndValue, batchSize = 500) {
  try {
    // コレクション参照を取得
    const collectionRef = db.collection(collectionName);
    
    // 並び替えに使うフィールド名
    const orderField= 'created_at';
    
    // 最初のバッチを取得するためのクエリを作成
    let query = collectionRef.orderBy(orderField).limit(batchSize);
    let documents = await query.get();
    
    // 更新された合計数
    let totalUpdatedCount = 0;
 
    // ドキュメントが存在する間ループを続ける
    while (documents.size > 0) {
      // バッチを作成
      let batch = firestore.batch();
      
      // 各ドキュメントを更新
      documents.forEach(document => {
        batch.update(document.ref, updatingFieldAndValue);
      });
 
      // バッチをコミット
      await batch.commit();
      
      // 更新された合計数を更新
      totalUpdatedCount += documents.size;
      console.log(`バッチ更新: ${documents.size} 件のドキュメントを更新しました。`);
 
      // 次のバッチのドキュメントを取得するためにクエリを更新
      query = collectionRef.orderBy(orderField)
        .startAfter(documents.docs[documents.docs.length - 1])
        .limit(batchSize);
      documents = await query.get();
    }
 
    // 更新成功のログメッセージ
    console.log(`コレクション ${collectionName} のドキュメントを正常に更新しました。合計: ${totalUpdatedCount} 件のドキュメントを更新しました。`);
  } catch (error) {
    throw error;
  }
}

下記のように使います。

// 使用例: todosというコレクションのドキュメントのstatusをdoneに更新する
updateDocumentsInBatches('todos', { status: 'done' });