로컬 PC에서 firebase-admin을 사용하여 일괄 삭제/일괄 업데이트

최근 Nuxt.js+Firebase로 만든 적독을 해소하는 웹 앱 "적독 하우 매치"을 출시했습니다! !

그 때 Firestore의 스키마를 일괄 변경하거나,
불필요한 데이터를 일괄 삭제하고 싶을 때의 비망록.

로컬 PC에서 firebase-admin을 사용할 때의 초기 설정이란?
- 로컬 PC에서 firebase-admin을 사용하여 Firestore 조작 (관리 도구) - 해파리가되고 싶다.

주의점



Firestore에서는 한 번에 실행할 수 있는 갱신 처리의 수에 제한이 있다.

대량 쓰기에서는 최대 500개의 작업을 수행할 수 있습니다.

트랜잭션 및 일괄 쓰기  |  Firebase

그 때문에, 이하에 기재되어 있는 바와 같이,
100건마다 등 작은 배치로 나누어 실행할 필요가 있다.

메모리 부족 오류를 방지하려면 작은 배치로 나누어 문서를 삭제하는 것이 좋습니다. 전체 컬렉션이나 하위 컬렉션이 삭제될 때까지 이 프로세스를 반복합니다.

Cloud Firestore에서 데이터 삭제하기 | Firebase

작은 배치로 나누어 실행하는 소스



전체적으로는 이런 느낌.

등장하는 3가지
  • main() ... 메인 함수. 실행할 때 호출되는 함수
  • deleteAllUsers() ... 사용자를 일괄 삭제하는 함수. main에서 호출
  • executeBatch() ... 지정된 배치 사이즈로 재귀 적으로 실행하는 함수. deleteAllUsers ()에서 호출

  • 또한, 콜렉션 users 속에 있는 문서에는,
    작성 일시의 타임 스탬프 createAt 의 문서 필드가 있다고 가정합니다.
    const admin = require("firebase-admin");
    
    // 配置したサービスアカウントの秘密鍵を取得
    const serviceAccount = require("./key/XXXXX.json");
    
    // firebase-adminを初期化
    admin.initializeApp({ credential: admin.credential.cert(serviceAccount) });
    
    // firestoreのインスタンスを取得
    const db = admin.firestore();
    
    
    /**
     * 一括実行処理の共通関数
     * @param {FirebaseFirestore.Firestore} db firestoreのインスタンス
     * @param {Number} limit 1回に実行するサイズ
     * @param {Function} queryFunc ドキュメントを検索するクエリを作成する関数。firestore.Queryを返す
     * @param {Function} executeFunc 削除や更新などを実行する関数。
     * @param {Object|undefined} last 検索でヒットした最後の要素。バッチサイズで繰り返す際に利用s
     */
    async function executeBatch(db, limit, queryFunc, executeFunc, last) {
    
      // queryFuncを使って対象のドキュメントを取得
      const query = queryFunc(db, last);
      const items = await query.limit(limit).get();
    
      // ドキュメントが1つも見つからなければ、終了
      if (items.size === 0) return;
    
      // executeFuncを使ってbatchに削除/更新処理を追加&コミット
      const batch = db.batch();
      for (let i = 0; i < items.size; i++) {
        executeFunc(db, batch, items.docs[i]);
      }
      await batch.commit();
    
      // リストの最後の要素を取得して、再帰実行
      const lastItem = items.docs[items.size - 1].data();
      return await executeBatch(db, limit, queryFunc, executeFunc, lastItem);
    }
    
    
    /**
     * すべてのユーザを削除
     */
    async function deleteAllUsers(db, limit) {
     // 検索部分の関数: 作成日時で昇順ソートして取得
     const queryFunc = (db, last) => {
        let query = db.collection("users").orderBy("createAt", "asc");
        if (!!last) query = query.startAfter(last.createAt);
        return query;
      };
    
      // 実行部分の関数: itemで該当のドキュメントを受け取るので削除
      const executeFunc = (db, batch, item) => {
        const docRef = db.collection("users").doc(item.id);
        batch.delete(docRef);
      };
    
      return await executeBatch(db, limit, queryFunc, executeFunc, undefined);
    }
    
    // ****************************
    // * MAIN
    // ****************************
    async function main() {
      console.log(`***** START MAIN *****`);
      // バッチサイズを100件で実行
      const limit = 100;
      await deleteAllUsers(db, limit)
      console.log(`***** END   MAIN *****`);
    }
    
    main().then();
    

    다른 처리에서도 공통적으로 사용할 수 있도록 executeBatch() 그럼,queryFuncexecuteFunc 의 2 개의 함수를 인수로 받을 수 있도록(듯이) 하고 있다.

    그래서 다른 처리 등을 추가할 때는 deleteAllUsers() 같은 것을 늘려 가면 OK!!

    이것으로 일괄 삭제나 스키마의 갱신도 상당히 편하게...(´ω`)

    결론



    Web 서비스는 운용하기 시작하면 여러가지 힘들기 때문에 관리 툴 등도 중요합니다.
    최근 출시한 이 앱에서도 사용하고 있습니다♪

    ■ 쌓아있는 책의 총액을 아는 독서 관리 서비스
    적독 하우 매치


    총액을 알면 조금은 읽고 있는 책을 읽으려고 생각하거나♪
    적독 총액 랭킹이나 인기의 책 등도 있으므로, 좋으면 어쩌면 받을 수 있으면!!

    적독 하우매치는 Nuxt.js+Firebase+ZEIT Now로 만들고 있습니다♪

    참고로 한 사이트


  • Cloud Firestore에서 데이터 삭제하기 | Firebase
  • Firestore에 테스트 데이터를 전송 | shogo yamada | note
  • Firestore의 특정 컬렉션에 대한 문서를 완전히 삭제하는 스크립트 (TypeScript 버전)
  • Cloud Firestore 백업 복원 - google-cloud-kr - Medium
  • 로컬 PC에서 firebase-admin을 사용하여 Firestore 조작 (관리 도구) - 해파리가되고 싶다.
  • 좋은 웹페이지 즐겨찾기