Firebase のデータベースを使って Firebase ストレージのファイル情報を10倍速く処理する方法!

記事
IT・テクノロジー

Firebase のデータベースを使って Firebase ストレージのファイル情報を10倍速く処理する方法!

Firebase ストレージにファイルを保存する場合、ファイルの追加情報をメタデータとして保存できます。 例えば、ファイルのタイトルや簡単な説明、分類などの情報をメタデータとして保存しておくと、ファイルの検索や表示をする際に便利です。この Firebase ストレージのファイル情報(メタデータ)の扱い方で性能が大きく変わることをご存知でしょうか?

この記事では、Firebase ストレージに保存されているファイルのファイル情報(メタデータ)の上手な扱い方を紹介しています。

Firebase ストレージに保存するファイル情報の基本

わかりやすく説明するために、ブログの投稿データを Firebase ストレージに保存する場合を考えます。

ブログの投稿なのでファイル情報(メタデータ)として以下の情報をファイルと一緒に保存します。

* タイトル(title)
* 投稿日時(date)
* 概要(description)
* 分類(type)

これを Firebase のメタデータとして保存する場合、Firebase のメタデータの「customMetadata」として保存することができます。 ファイルをアップロードする際にはメタデータを追加して Firebase ストレージにアップロードするだけです。

function fileUpload(file:File, folder:string) {
    const fileRef:firebase.firestore.Reference = firebase.storage().ref().child(folder)
    // Firebaseストレージのメタデータ
    const fbMetadata: firebase.storage.UploadMetadata = {
        contentType: "text/plaintext",
        customMetadata:{
            title: "title",
            date: "2021-02-28",
            description: "description",
            type: "sample"
        }
    }
    const task:firebase.storage.UploadTask = fileRef.upload(file,fbMetadata);

    ........
    ........
}
このデータを取得して、ファイルの一覧などを表示する際にファイル名だけではなく、こうしたファイルの中身に関する情報を一緒に表示できると利用者にとって使いやすいアプリやサービスにすることができます。また、ファイルの検索などにも応用できます。投稿の本文の中身を検索するのではなく、キーワードをファイル情報(メタデータ)に入れたりすると、検索を効率よく行うことができるからです。

ファイル情報の取り出し方

Firebase ストレージに保存されているファイルのファイル情報(メタデータ)を取り出す手順は以下のような手順になります。

* ファイルのリファレンスリストの取得
* ファイルのリファレンスからファイル情報(メタデータ)を取得
ファイルのリファレンスは、ファイルが保存されている「場所」です。これは、フォルダ(Firebase の用語ではバケット)を基に、その中にあるファイルのリファレンスを取得できます。詳細は以前の記事で紹介しています。

ファイル情報(メタデータ)を取得するには、このフィアルのリファレンスから取得する必要があります。ファイルのリファレンスが「ref」の場合は「ref.getMetadata()」を呼び出すと取得できます。

取り出すこと自体は簡単なのですが、この両方の処理、リファレンスのリストの取得と、ファイル情報の取得は「非同期」の処理として行われます。

一つ一つのファイルを個別に処理する場合は余り大きな問題ではありませんが、あるフォルダに複数のファイルがある場合にまとめてファイル情報を取得したい場合は注意が必要になります。

以下のコードは Firebase のストレージからファイルの情報をまとめて取得する例です。

static getMetaDataFromStorage(
    folder: string
  ): Promise<Array<TYPE.FileInformation>> {
    return new Promise((resolve: any): void => {
      const files: Array<TYPE.FileInformation> = [];
      firebase
        .storage()
        .ref()
        .child(folder)
        .listAll()
        .then(async (res: firebase.storage.ListResult) => {
          for (let i = 0; i < res.items.length; i++) {
            const itemRef: firebase.storage.Reference = res.items[i];
            const metadata: any = await MyFirebase.getMetadata(itemRef);
            if (metadata) {
              const fileInfo: TYPE.FileInformation = {
                name: itemRef.name,
                path: folder,
                title: metadata.title,
                date: metadata.date,
                description: metadata.description,
                type: metadata.type,
              };
              files.push(fileInfo);
            } else {
            }
          }
          resolve(files);
        })
        .catch((error: any) => {
          resolve([]);
        });
    });
  }
ファイルのリファレンスのリストを取得した後は、個別にメタデータの取得を待って、一つづつ順番にメタデータの配列(array)に入れる必要があります。

ファイル情報を取り出すのに必要な時間は?

Firebase のストレージからファイル情報(メタデータ)の一覧を取り出すのにどれ位時間がかかるか計測してみました。 サンプルでは、ブログの投稿の記事22個分のデータを取得する時間を測ってみました。結果は平均で「2〜4秒」でした。

ファイル1個分の情報で約 0.1〜0.2 秒という計算です。

これだけでは、この処理が速いのか遅いのかよくわかりませんよね?

そこで、Firebase ストレージのメタデータではなく、ファイル情報を Firebase のデータベース(Cloud Firestore)に保存したらどうなるかを試してみました。

Firebase のデータベース(Cloud Firestore)に保存するドキュメントのデータは以下の様なものにしました。

{
  "name": "file name",
  "path": "folder name",
  "title": "title",
  "date": "date",
  "description": "description",
  "type": "type"
}
Firebase のストレージのメタデータに加えて、ファイルの名前と、フォルダの名前を追加しています。これは、このデータからファイルの場所を Firebase ストレージから取得できるようにするためです。

このデータを Firebase ストレージにファイルをアップロードする場合に一緒に Firebase のデータベース(Cloud Firestore)に保存します。

ファイルの情報が必要な場合は、Firebase ストレージからではなく Firebase のデータベース(Cloud Firestore)から取得するように変更してみました。

      ストレージのメタデータ(秒)   データベース(秒)
1回目    3.8              0.38
2回目    2.1              0.16
3回目    2.5              0.28
4回目    2.5              0.17
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
平均     2.7              0.24
この方法で同じファイルの情報を取得するのに必要な時間は「0.1〜0.4 秒」です。Firebase ストレージのメタデータを取得する時間に比べると10倍速くなっています。

(*)最初の処理時間が遅いのは、キャッシュメモリにプログラムが入っていない事が関係していると推定されます。2回目以降の処理時間は概ね同じです。

まとめ
Firebase ストレージを利用する際に保存するファイルの情報をメタデータとして保存すると、一覧を表示したりする際に便利です。 しかし、2つの非同期処理が必要なために、データを取得するのには時間がかかります。実装が少し面倒になりますが、Firebase ストレージのメタデータの代わりに Firebase データベース(Cloud Firestore)に同じ情報を保存しておくと、10倍速くデータを取り出す事が可能です。

ちょっとした工夫ですが、利用者にはサービスやアプリの印象が大く変わってしまう位処理スピードが違います。

Firebase を利用する際には、同じ機能でも、使い方を少し変えるだけで性能が大きく変わる場合もあります。Firebase の特長をうまく利用してより、利用者に快適なサービスやアプリを目指すとより価値が高く人気のサービスにする事ができます。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す