できたこと
FirebaseのFirestoreを使っており、その更新作業を自動でできないか考えた。
Cloud StorageへのExcelアップロードをトリガーにCloud functionsを発火させ、Firestoreの更新が行われる仕組みづくりをしてみた。
意外と面倒だったのでメモメモ。
コード
実装全体
これをcloud functionsへデプロイ。
今回はNode.jsで記述。
//もろもろ
const cors = require('cors')({ origin: true });
const path = require('path');
const os = require('os');
const functions = require('firebase-functions')
//必要な情報
const keyFilename = "path/to/keyfile";
const projectId = "YOUR PROJECT ID";
//おまじない
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
const gcs = require('@google-cloud/storage')({
    projectId,
    keyFilename
});
const bucket = gcs.bucket("YOUR BUCKET NAME");
//ここからが処理内容
exports.helloWORLD = (event, context) => {
  //トリガーの内容はeventかcontextに入る
  const gcsEvent = event;
  const file_name = event.name
  const tempFilePath = path.join(os.tmpdir(), file_name);
  //gcs bucketからexcelをダウンロードする
  //一時ファイルとしてfunctionsのローカル環境にダウンロードする
  bucket
    .file(file_name)
    .download({
      destination: tempFilePath
    })
    .catch(err => {
      console.error('テンプレファイルダウンロードエラー:', err);
    })
    .then(() => {
      //Excelの処理に必要なおまじない
      let XLSX     = require('xlsx')
      let workbook = XLSX.readFile(tempFilePath)
      
      //Excelの取ってきたいデータを参照
      let sheet_name_list = workbook.SheetNames
      let Sheet1          = workbook.Sheets[sheet_name_list[0]]  // 1つめのシートデータを取得します
      let sheet_info_json     = XLSX.utils.sheet_to_json( Sheet1 )   // データをJSONパースします
      //Firestoreにぶち込むための入れ物
      let input_info = []
      //各行のデータが一つずつclに入る。cl[列のタイトル]でデータが取り出せる
      for (let cl of sheet_info_json){
        input_info.push({"name":cl["品目"],"price":cl["値段"]})
      }
      // データベースの参照を作成
      var fireStore = admin.firestore()
      var citiesRef = fireStore.collection(YOUR COLLECTION NAME);
      citiesRef.doc(YOUR DOCUMENT NAME).set({
        data: input_info}
      )
   }) //then
}; //export
package.jsonの中身はこちら。
{
  "name": "sample-cloud-storage",
  "version": "0.0.1",
  "dependencies": {
    "@google-cloud/storage": "^1.6.0",
    "cors":"^2.8.5",
    "firebase": "^7.14.2",
    "firebase-admin": "^8.6.0",
    "firebase-functions": "^3.3.0",
    "os":"^0.1.1",
    "path":"^0.12.7",
    "xlsx":"^0.16.9"
  }
}
実装こまごま
GCS⇔cloud functionsの連携
こちらの記事を無茶苦茶参考にしました。
cloud storageにあるExcelを一旦ローカルに保存するという発想もこちらのものです。
GCSのファイナライズをトリガーにしていますが、eventやcontextの中身についてはFirebaseの公式サイトをご覧ください。
pythonで実装された人の記事はこちらやこちらからご覧ください。
個人的に「バケット名ってどこからどこまでやねん」となりましたが、gs://ultra-soul.appspot.comの場合、ultra-soul.appspot.comがバケット名です。
公式ドキュメントに書かれていたけど全然気づかなかった。。。
cloud functions内のExcelの処理
Excelをいじれるモジュールはいろいろあるみたいで、今回はxlsxを利用しました。
幾つか調べものをした結果をここにも載せておきます。
・exceljsモジュール
 便利そうで実際ハンズオンしたけれど、今回の目的には少し使いにくかった。
 npm公式サイトはこちらから
・xlsxモジュール
 今回はこちらを利用!参考記事はこちらから
ちなみにcsvの場合はこちらの記事が便利そう。
csvばかりでExcelをインポートするための情報が少なすぎて苦労しました。。。
cloud functions⇔Firebase firestoreの連携
こちらの記事を無茶苦茶参考にしました。
collectionとかdocumentとかの設計についてはこちらの記事を参考にしました。
collectionは検索するのが難しく、documentは検索がサクッと行えるのが私個人的な実感。
APIドキュメントはこちらから
Firebase CLIを使ったデプロイ
これは素直に公式ドキュメントを参考にしました。
CLI上でプロジェクトの切り替えの方法はこちらから
使い慣れると便利!!
最後に
pythonでも実装してみたいなぁ