Firebase データベースのデータの更新イベントの検出

記事
IT・テクノロジー

Firebase データベースのデータの更新イベントの検出

データベースを利用したアプリやサービスを開発する場合、データベースのデータがアプリやサービスの利用中に更新される場合があります。そうした場合、どのようにすれば現在利用中のデータの更新ができるかがポイントになります。Firebase のデータベース(Cloud Firestore)はこうしたケースを想定したインターフェースを予め用意しています。

この記事では、Firebase のデータベース(Cloud Firestore)のデータが更新された場合にどのように更新されたデータを取得するかを紹介しています。

オンラインショップのサイトを例に考えてみます!

サービスの利用中にデータベースのデータが更新されて、そのデータの更新が必要な場合と言ってもなかなか思い当たらないと思いますので、もう少し具体的に例を挙げて説明します。

例えばオンラインショッピングのサイトを作成する場合を考えてください。 サイトで販売する商品を表示して、気に入った商品があれば購入して決済をするようなサービスになります。

サイト全体ではいろいろな機能が必要になります。商品の紹介から、決済や質問なども含めて、たくさんの機能を実装する必要があると思います。そして、いろいろな場面でデータの更新をする場面もあると思いますが、この記事では商品情報を表示する部分に絞って考えます。

商品情報の表示で必要な情報は?

商品情報を表示するに当たっていろいろな情報が必要になります。 販売する商品によっていろいろ変わってくる部分もありますが、一般的に考えて共通して必要な内容は:

* 商品の説明や紹介
* 価格
です。これらは基本的にショッピングする上で必要な情報です。 これに加えてもう一つ大切な情報があります。実際には、商品情報の表示で画面に出さない場合も多いですが、「在庫情報」は重要な情報の一つです。 オンラインショップでよく見る表示には

* 在庫が少ない場合は、その旨を表示して「早期購入」を促す
* 在庫がない場合は、商品の表示そのものをやめる
* 在庫がない場合は、商品の表示はするが、売り切れであることを表示する
 などがあります。こうした表示を行うための処理が通常は必要になるからです。
商品の在庫情報が変わる時はいつ?
では、次に「いつ」商品の在庫情報が変わるかを考えてみてください。 基本的には以下の2つです:

* 商品が売れた場合
* 商品が新規に入荷した場合
他の要素もありますが、殆どの在庫数の変化は販売と入荷によって変わります。

多数の人が同時に閲覧可能なオンラインショッピングのサイトは、サイトで商品を選んでいる間にも別の利用者が商品を購入したりして在庫がなくなる場合が考えられます。また、売り切れの商品でも新たに入荷すれば販売することが可能です。

そう考えると、販売や入荷で在庫数が変化した場合、利用者の見る情報も更新する事が好ましいのは言うまでもありません。一つの方法としては、利用中に定期的にデータベースのデータをチェックして、在庫数が変化したら表示データを更新すると言う処理を行えば、問題は解決できます。

しかし、問題は「いつ変わるかわからない」ので不必要なデータベースアクセスを行う必要があります。しかし、あまりチェックする間隔の時間が長いと、在庫情報が反映されるまで時間がかかることになるので、利用者としては、不便になってしまします。

Firebase のデータベースの「onSnapshot」を使えば解決!

Firebase のデータベース(Cloud Firestore)には、特定のデータベースのデータが更新されたのを検出して処理する機能が予め用意されています。それが、前回も紹介した「onSnapshot」と言う機能です。

例えば、ある商品のデータを「products」と言うコレクションに、入れている場合には、以下のような記述で処理できます。

firebase
  .firestore()
  .collection("products")
  .doc("ABCD")
  .onSnapshot((doc) => {
    update_display(doc.data());
  });
のように書くと、コレクションの中の「ABCD」と言うドキュメント ID のデータが変わったら、表示を更新すると言うような処理ができます。「update_display((doc.data())」は、商品の表時データを更新する関数です。ここに必要な処理を書いておけば、指定したドキュメントのデータの中身が更新されると、この関数が呼ばれるという事です。

React などの場合は、ここで読み込んだデータ(例では、「doc.data()」)を変数に入れて、ステートで管理しておけば、値が変化すると、React のフレームワークが表示の更新をしてくれます。

この例では、特定の「ドキュメント」の更新を監視するような処理ですあ、コレクション全体の変化も監視して処理する事ができます。

class Sample extends React.Component {
    constructor() {
        super();
        this.init();
        this.state = {
            samples:[]
        }
    }
    init() {
        firebase.firestore().collection("products").onSnapshot((querySnapshot) => {
            const samples = []
            for (let i = 0 ; i < querySnapshot.size ; i++)
                const doc = querySnapshot.docs[i]
                samples.push(doc.data())
            })
            this.setState({
                samples: samples
            })
        })
    }
    render() {
        return(
            <table>
                <thead>
                    <tr>
                        <th>商品名</th>
                        <th>価格</th>
                        <th>在庫数</th>
                    </tr>
                </thead>
                <tbody>
                    {this.state.samples.map((sample) => (
                        <tr key={sample.id}>
                            <td>{sample.name}</td>
                            <td>{sample.price}</td>
                            <td>{sample.stock}</td>
                        </tr>
                    ))}
                </tbody>
            </table>

        )
    }
}
React コンポーネントをクラス形式で書いた例ですが、このようにすると、「samples」のコレクションのデータが変化すると、「onSnapshot」の処理が呼び出されて、ステートで管理している変数の「samples」を更新するので、React のフレームワークがテーブルのデータを更新してくれます。

これは、利用者が閲覧中でも、Firebase のデータベースが更新されると自動的に表示データを更新できるようになります。

まとめ
Web アプリや Web サービスではアプリやサービスの利用中に、表示や機能に関係した情報が更新される事は頻繁に起こります。こうした場合に、既にデータベースから取得しているデータが実際のデータベースのデータと違う場合はよく発生します。こうした、データの一貫性の問題を解決するには、データベースのデータと実際に利用しているデータを同期して同じデータにする必要があります。

こうした場合でも、Firebase のデータベースを利用している場合、最初に「onSnapshot」でデータを取得しておけば、その後は特別なコードを書かなくてもデータの更新を簡単に行うことができます。

自分でゼロからこうした機能を実装するのは手間がかかりますが、Firebase はそうした「基本的な」機能は予め用意して提供してくれます。この辺りが、初心者でも完成度の高い、こう付加価値のシステムを簡単に作成できる秘密です!
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す