データの重複は NoSQL ではほぼ一般的であるため、カウンターを保存することは完全に合理的です。非正規化に関する Firebase の記事をご覧ください
これは、私が理解しているアプローチをほぼ要約しています。
カウンターの使用
優れた DRY 原則を使用し、レコードのすべての操作を集中管理していると仮定すると、高速であり、かなり単純です。トランザクションを利用して、レコードが追加または削除されるたびにカウンターを更新します。
function addUser(user) {
// do your add stuff...
updateCounter(1);
}
function removeUser(user) {
// do your remove stuff...
updateCounter(-1);
}
function updateCounter(amt) {
userCounter.transaction(function(currentValue) {
currentValue || (currentValue === 0); // can be null
return currentValue + amt;
});
}
公開データと保護データを分離する
機密データ (電子メール アドレス、人々が見ることができないもの) をプライベート パスに保存し、パブリック ユーザー データを読み取り可能な状態に保ちます。
これにより、カウンターを同期する必要がなくなります。ただし、これはクライアントがパブリック ユーザーのリスト全体をダウンロードしてカウントを作成する必要があることを意味します。そのため、パブリック プロファイルを小さく (名前、タイムスタンプなど) 維持して、数秒もかからずに数万人に対応できるようにします。
"users": {
".read": true,
"$user": {
// don't try to put a ".read" here; it won't remove access
// after the parent path allows it
}
}
"users_secured": {
"$user": {
".read": "auth.id === $user"
}
}
サーバープロセスを利用する
簡単で無痛; クライアントにとって非常に高速であり、フットプリントが小さい限り、何十万ものプロファイルを簡単に処理できます。何かを維持する必要があります。HerokuとNodejitsuは、ユーザーが耳から離れなくなるまで、これを無料でホストします。
var Firebase = require('firebase');
var fb = new Firebase(process.env.FBURL);
fb.auth( process.env.SECRET, function() {
fb.child('users').on('value', function(snap) {
fb.child('user_counter').set( snap.numChildren() );
});
}