Firestoreにおける(クライアント側)集計


RDBと違い、Firestoreにおける集計は原則クライアント再度で行う必要があります。
その際の基本的なメモ。なお、JSにおける(配列の)集計処理にはreduceを使うことになりますが、それについてはこちらの記事をご覧ください。

前提

  • firebase-adminを利用してみます。
  • 秘密鍵は準備されているものとします。

テストデータの作成

下記のようなデータをfirestoreに登録します。

createData.js
const admin = require('firebase-admin');
admin.initializeApp({
    credential: admin.credential.cert("/path/to/key.json"),
    databaseURL: "https://xxxxxxxx.firebaseio.com"
});

const db = admin.firestore();

const commodities = [
    { id: 1, name: "apple", category: "fruit", price: 300 },
    { id: 2, name: "cucumber", category: "vegetable", price: 100 },
    { id: 3, name: "orange", category: "fruit", price: 300 },
    { id: 4, name: "grape", category: "fruit", price: 100 },
    { id: 5, name: "cabbage", category: "vegetable", price: 200 },
];

(() => {

    commodities.map(async item => {
        await db.collection("sales").add(item);
    })

    console.log("完了");

})()

key名とかしっくりこないけど、まあとりあえずOKとする。

データの集計

登録が完了したら集計してみます。

getSummary.js
const admin = require('firebase-admin');
admin.initializeApp({
    credential: admin.credential.cert("/path/to/key.json"),
    databaseURL: "https://xxxxxxxx.firebaseio.com"
});

const db = admin.firestore();

(async () => {

    //get data
    const snapshot = await db.collection("sales").get();

    //sum(単純計算)
    const sum = snapshot.docs
        .map(doc => doc.data().price)
        .reduce((prev, current) => prev + current, 0);

    console.log(sum);

    //groupBy(データ整形)
    const groupBy = snapshot.docs
        .map(doc => doc.data())
        .reduce((prev, current) => {
            const element = prev.find(value => value.category === current.category);
            if (element) {
                element.count++;
                element.price += current.price;
            } else {
                prev.push({
                    category: current.category,
                    count: 1,
                    price: current.price,
                });
            }
            return prev;
        }, []);

    console.log(groupBy);

})()

実行結果

下記のような結果が得られるはずです。これをダッシュボード等に描画したり、帳票で出したりすることになります。

1000

[
  { category: 'fruit', count: 3, price: 700 },
  { category: 'vegetable', count: 2, price: 300 }
]