を介して子の数を取得できます
firebase_node.once('value', function(snapshot) { alert('Count: ' + snapshot.numChildren()); });
しかし、これはサーバーからそのノードのサブツリー全体を取得すると考えています。巨大なリストの場合、RAMおよび遅延が集中するようです。すべてを取得せずにカウント(および/または子名のリスト)を取得する方法はありますか?
実際に指定したコードスニペットは、データセット全体をロードし、クライアント側でカウントします。これは、大量のデータの場合は非常に遅くなる可能性があります。
Firebaseには現在、データをロードせずに子をカウントする方法はありませんが、追加する予定です。
今のところ、1つの解決策は、子の数のカウンターを維持し、新しい子を追加するたびにそれを更新することです。次のコード追跡アップボードのように、トランザクションを使用してアイテムをカウントできます。
var upvotesRef = new Firebase('https://docs-examples.firebaseio.com/Android/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes');
upvotesRef.transaction(function (current_value) {
return (current_value || 0) + 1;
});
詳細については、 https://www.firebase.com/docs/transactions.html を参照してください
UPDATE:Firebaseは最近Cloud Functionsをリリースしました。 Cloud Functionsを使用すると、独自のサーバーを作成する必要がありません。 JavaScript関数を作成して、Firebaseにアップロードするだけです。 Firebaseは、イベントが発生するたびに機能をトリガーします。
たとえば、アップ投票をカウントする場合は、次のような構造を作成する必要があります。
{
"posts" : {
"-JRHTHaIs-jNPLXOQivY" : {
"upvotes_count":5,
"upvotes" : {
"userX" : true,
"userY" : true,
"userZ" : true,
...
}
}
}
}
そして、upvotes
ノードへの新しい書き込みがあるときに、upvotes_count
を増やすためにjavascript関数を記述します。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.countlikes = functions.database.ref('/posts/$postid/upvotes').onWrite(event => {
return event.data.ref.parent.child('upvotes_count').set(event.data.numChildren());
});
ドキュメント を読んで、 クラウド機能の使用を開始する の方法を知ることができます。
また、投稿をカウントする別の例はこちらです: https://github.com/firebase/functions-samples/blob/master/child-count/functions/index.js
firebase docs が変更されたため、event
の代わりにchange
とcontext
が追加されました。
与えられた例は、event.data
が未定義であるという文句を言うエラーを投げます。このパターンはよりよく機能するようです:
exports.countPrescriptions = functions.database.ref(`/prescriptions`).onWrite((change, context) => {
const data = change.after.val();
const count = Object.keys(data).length;
return change.after.ref.child('_count').set(count);
});
`` `
いくつかの他の人がすでにうまく答えているので、これはゲームの少し遅れていますが、私はそれを実装する方法を共有します。
これは、 Firebase REST API がshallow=true
パラメーターを提供するという事実にかかっています。
post
オブジェクトがあり、それぞれがいくつかのcomments
を持つことができると仮定します。
{
"posts": {
"$postKey": {
"comments": {
...
}
}
}
}
もちろん、すべてのコメントを取得するのではなく、コメントの数だけを取得する必要があります。
投稿のキーがあると仮定すると、GET
リクエストをhttps://yourapp.firebaseio.com/posts/[the post key]/comments?shallow=true
に送信できます。
これは、キーと値のペアのオブジェクトを返します。各キーはコメントのキーであり、その値はtrue
です。
{
"comment1key": true,
"comment2key": true,
...,
"comment9999key": true
}
このレスポンスのサイズは、同等のデータをリクエストするよりもはるかに小さいため、レスポンス内のキーの数を計算して値を見つけることができます(例:commentCount = Object.keys(result).length
)。
返されるキーの数をまだ計算しているため、これは問題を完全には解決しない可能性があり、値が変更されるたびにサブスクライブする必要はありませんが、変更することなく返されるデータのサイズを大幅に削減しますスキーマ。
カウントを保存します-検証を使用して強制します。私はこれを一緒にハックしました-ユニークな投票とカウントのカウントを維持するために、これからも続きます!しかし、今回は提案をテストしました! (切り取り/貼り付けエラーにもかかわらず!)。
ここでの「トリック」は、ノードpriority toを投票数として使用することです...
データは次のとおりです。
vote/$ issueBeingVotedOn/user/$ uniqueIdOfVoter = thisVotesCount、priority = thisVotesCount vote/$ issueBeingVotedOn/count = 'user /' + $ idOfLastVoter、priority = CountofLastVote
,"vote": {
".read" : true
,".write" : true
,"$issue" : {
"user" : {
"$user" : {
".validate" : "!data.exists() &&
newData.val()==data.parent().parent().child('count').getPriority()+1 &&
newData.val()==newData.GetPriority()"
ユーザーは1回しか投票できません。&&カウントは現在のカウントより1つ高くなければなりません。
}
}
,"count" : {
".validate" : "data.parent().child(newData.val()).val()==newData.getPriority() &&
newData.getPriority()==data.getPriority()+1 "
}
count(実際には最後の投票者)-投票が存在する必要があり、そのカウントはnewcountに等しく、&& newcount(優先順位)は1つだけ増加できます。
}
}
さまざまなユーザーによる10票を追加するテストスクリプト(この例では、IDが偽造されているため、ユーザーはauth.uidを運用する必要があります)。 (i--)10カウントダウンして、検証が失敗したことを確認します。
<script src='https://cdn.firebase.com/v0/firebase.js'></script>
<script>
window.fb = new Firebase('https:...vote/iss1/');
window.fb.child('count').once('value', function (dss) {
votes = dss.getPriority();
for (var i=1;i<10;i++) vote(dss,i+votes);
} );
function vote(dss,count)
{
var user='user/zz' + count; // replace with auth.id or whatever
window.fb.child(user).setWithPriority(count,count);
window.fb.child('count').setWithPriority(user,count);
}
</script>
ここでの「リスク」は、票が投じられるが、カウントが更新されないことです(ハッキングまたはスクリプトの失敗)。これが投票に一意の「優先度」がある理由です-スクリプトは実際に、現在のカウントよりも高い優先度の投票がないことを確認することから開始する必要があります。あなたのために:)
カウントを開始する前に優先度で初期化する必要があります-forgeではこれを実行できないため、スタブスクリプトが必要です(検証がアクティブになる前に!)。
クラウド関数を記述してノード数を更新します。
// below function to get the given node count.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.userscount = functions.database.ref('/users/')
.onWrite(event => {
console.log('users number : ', event.data.numChildren());
return event.data.ref.parent.child('count/users').set(event.data.numChildren());
});
参照: https://firebase.google.com/docs/functions/database-events
ルート-| | -users(このノードにはすべてのユーザーリストが含まれます)|
| -count | -userscount:(このノードは、クラウド機能によりユーザー数とともに動的に追加されます)