您可以通过以下方式获得孩子人数
firebase_node.once('value', function(snapshot) { alert('Count: ' + snapshot.numChildren()); });
但是我相信这可以从服务器获取该节点的整个子树。对于庞大的列表,这似乎需要占用大量RAM和延迟。有没有一种方法可以获取计数(和/或子名称列表)而无需获取整个信息?
您可以通过以下方式获得孩子人数
firebase_node.once('value', function(snapshot) { alert('Count: ' + snapshot.numChildren()); });
但是我相信这可以从服务器获取该节点的整个子树。对于庞大的列表,这似乎需要占用大量RAM和延迟。有没有一种方法可以获取计数(和/或子名称列表)而无需获取整个信息?
Answers:
您提供的代码段确实确实加载了整个数据集,然后在客户端对其进行计数,这对于大量数据而言可能非常慢。
Firebase当前无法在不加载数据的情况下对儿童进行计数,但是我们确实计划添加它。
目前,一种解决方案是维护一个子代数计数器,并在每次添加新子代时对其进行更新。您可以使用事务来计数项目,如下面的代码跟踪升级:
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
更新: Firebase最近发布了Cloud Functions。使用Cloud Functions,您无需创建自己的服务器。您只需编写JavaScript函数并将其上传到Firebase。每当发生事件时,Firebase都会负责触发功能。
例如,如果您要计算投票数,则应创建与此结构类似的结构:
{
"posts" : {
"-JRHTHaIs-jNPLXOQivY" : {
"upvotes_count":5,
"upvotes" : {
"userX" : true,
"userY" : true,
"userZ" : true,
...
}
}
}
}
然后编写一个javascript函数来增加upvotes_count
对upvotes
节点的新写操作。
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());
});
您可以阅读文档以了解如何开始使用Cloud Functions。
另外,这里还有另一个计数帖子的示例:https : //github.com/firebase/functions-samples/blob/master/child-count/functions/index.js
在火力文档已经改变所以不是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
)。
这可能无法完全解决您的问题,因为您仍在计算返回的键数,并且不一定要在值更改时订阅该值,但是它确实减小了返回数据的大小,而无需更改您的值模式。
.json
在URL末尾附加例如:https://yourapp.firebaseio.com/posts/comments.json?shallow=true
随手保存计数-并使用验证强制执行。我一起砍了这个-为了保留唯一的票数和不断增加的票数!但是这次我测试了我的建议!(尽管剪切/粘贴错误!)。
这里的“技巧”是使用节点优先级作为投票计数...
数据为:
投票/ $ issueBeingVotedOn /用户/ $ uniqueIdOfVoter = thisVotesCount,优先级= thisVotesCount投票/ $ issueBeingVotedOn / count ='用户/'+ $ idOfLastVoter,优先级= 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()"
用户只能投票一次&&计数必须比当前计数高一个&&数据值必须与优先级相同。
}
}
,"count" : {
".validate" : "data.parent().child(newData.val()).val()==newData.getPriority() &&
newData.getPriority()==data.getPriority()+1 "
}
计数(实际上是最后一个投票者)-投票必须存在并且其计数等于newcount,&& newcount(优先级)只能增加一。
}
}
测试脚本以添加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 :(此节点由云功能根据用户数量动态添加)