💭

Cloud StoregeにCSVファイルを置いたら、 Cloud Function経由でFirestoreにデータを入れる

2024/08/30に公開

はじめに

  • Cloud Storageにアップした大きめのCSVファイルを、Cloud FunctionでFirestoreにインポートする方法をまとめました。
  • 覚書程度に残してありますので、汚いのはご了承ください😓(要望があれば綺麗にしようかと)

環境

  • Cloud Functions(第二世代)
  • Cloud Storage
  • Node.js

概要

  • ユーザーがCSVファイルをアップロードしたら、Cloud Function経由でFirestoreにデータを入れる
const functions = require('@google-cloud/functions-framework')
const admin = require('firebase-admin')
const { parse } = require('csv-parse')

admin.initializeApp()

functions.cloudEvent('importCsvToFirestore', async (cloudEvent) => {
  const db = admin.firestore()

  // cloudEventからバケット名とファイル名を取得
  const file = cloudEvent.data
  console.log(`Bucket: ${file.bucket}, File: ${file.name}`)

  const bucket = admin.storage().bucket(file.bucket)
  const remoteFile = bucket.file(file.name)
  const parser = parse({
    columns: true,
    skip_empty_lines: true,
  })

  // ファイルを読み込む
  remoteFile
    .createReadStream()
    .pipe(parser)
    .on('readable', async () => {
      // バッファに読み込み可能なデータが溜まったら、バッチに書き込む
      // 一回の Cloud Function の実行で、何度か実行されることに注意
      let batch = db.batch()
      let batchCount = 0 // バッチ内の書き込み回数
      let record
      while ((record = parser.read())) {
        // 1行ずつ読み込み
        const ref = db.doc(`path/to/doc`)

        batch.set(ref, {
          ...record,
          userId: Number(record.userId), // 数値型で保存したい場合は、Number()でラップしないと文字列に
        }) // 1行ずつFirestoreに書き込み

        batchCount++
        // バッチ書き込みの上限は500件
        if (batchCount >= 495) {
          // バッチ書き込みの上限
          await batch.commit()
          batch = db.batch()
          batchCount = 0
        }
      }

      if (batchCount > 0) {
        await batch.commit()
      }
    })
    .on('error', (err) => {
      console.error('CSVパースエラー:', err)
    })
    .on('end', async () => {
      console.log('CSVファイルの処理が完了しました。')
    })
})
GitHubで編集を提案

Discussion