0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GCSへのExcelアップロードをトリガーにFirestoreを更新する

Posted at

#できたこと
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でも実装してみたいなぁ

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?