📘

Firestoreのデータの扱い方に関するメモ

2020/09/29に公開

概要

最近、Firestoreを触ってみたので、そのまとめなどを書いてみたいと思います。基本は公式のドキュメントに書いてあるのですが、自分が実現したいものがある時にどのような実装を選択すれば良いのかというのが、少しイメージが湧きずらかったので。個人的に咀嚼した内容を交えて、今回の記事とします。

前提

データの形式について

FirestoreはNoSQLのデータベースに分類されて、ドキュメント(json)形式でデータ保持をしています。MongoDBに近いですね。データの保持について、詳細はこちらのドキュメントに書かれています。

ざっくり概念のイメージとして、コレクションがRDBで言うところのテーブル、ドキュメントがレコードと位置付けられます。ドキュメントはjsonに似た形式で保持していて、ドキュメントについては1ドキュメント毎にIDが割り振られます。ドキュメント配下にはサブコレクションという形でデータを持てるようなのですが、データ構造が分かりにくくなりそうなので、個人的にはあまり使わないほうが良いかなと感じました。。
実際の画面で参照できるイメージは、以下のようになります。

データの取得

データの取得についてはドキュメントIDを指定する方法と、where句でコレクションから該当条件を指定して取得する方法にざっくり分かれてます。こちらの公式ドキュメントに詳細は書かれていますが、簡単な実装サンプルをのせておきます。

【ドキュメントIDを指定する方法】

const db = firebase.firestore();
db.collection("collecton_name").doc("doc_name").get()
  .then((doc) => {
    const data = doc.data();
    // データ取得後の処理
  })
  .catch((error) => {
    // エラー時の処理
  });

【where句で抽出する方法】

const db = firebase.firestore();
db.collection("collecton_name").where("status", "==", "active").get()
  .then((docs) => {
    docs.forEach((doc) => {
      const data = doc.data();
      // データ取得後の処理
    });
  });
  .catch((error) => {
    // エラー時の処理
  });

また、この取得データを監視して、リアルタイムに更新されるデータを取得する方法もあります。詳細は[Firebase] Firestoreでリアルタイムなチャットを作る (Web編) その1の記事にありますが、snapshotという機能を使うことで実現可能です。
以下がコレクションに対して、追加が行われた際のsnapshot取得の実装サンプルです。

const db = firebase.firestore();
db.collection("collecton_name");
  .orderBy("created_at", "asc")
  .limit(10)
  .onSnapshot((snapshot) => {
    snapshot.docChanges().forEach((change) => {
      if (change.type === "added") {
        const data = change.doc.data();
	// データ取得後の処理
      }
    });
  });

データの更新(1件ずつ)

次にデータの更新についてです。この項では、追加・更新・削除を1件ずつ行う方法を紹介します。Firestoreのデータ操作(取得, 追加, 更新, 削除)の記事に詳細は書かれていますが、簡単にサンプルをのせておきます。

まず追加ですが、基本コレクションを指定して追加したドキュメントのオブジェクトを追加する形になります。

【追加】

const db = firebase.firestore();
db.collection("collecton_name")
  .add({ name : "sample_add"})
  .then((ref) => {
    // 成功時の処理
  })
  .catch((error) => {
    // エラー時の処理
  });

更新は1件ピンポイントの場合は、ドキュメントIDを指定して行います。

【更新】

const db = firebase.firestore();
db.collection("collecton_name").doc("doc_id")
  .update({ name : "sample_update"})
  .then((ref) => {
    // 成功時の処理
  })
  .catch((error) => {
    // エラー時の処理
  });

削除も1件ピンポイントの場合は、ドキュメントIDを指定して行います。

【削除】

const db = firebase.firestore();
db.collection("collecton_name").doc("doc_id")
  .delete()
  .then((ref) => {
    // 成功時の処理
  })
  .catch((error) => {
    // エラー時の処理
  });

データの更新(バッチ処理)

最後に複数件のレコードを、一気にバッチ処理したい場合はどうすれば良いかということで、バッチ処理の機能について紹介します。FirestoreでBatch処理の記事に紹介されている通り、Firestoreではバッチの機能が用意されています。クライアントでも実行可能と思いますが、サーバサイドで実行した方が良いでしょう。一件留意点としては、一度に処理できる件数が500件までなので、バッチも500件単位で処理を区切らなければいけない点です。

Discussion