在Firebase中,有没有办法在不加载所有节点数据的情况下获取节点的子节点数?
你可以通过获得小孩的数量
firebase_node.once('value', function(snapshot) { alert('Count: ' + snapshot.numChildren()); });
但我相信这会从服务器获取该节点的整个子树。 对于巨大的列表,这似乎RAM和延迟密集型。 有没有获取计数(和/或一个儿童名单列表)的方式,而没有取得整个事情?
你给出的代码片段确实加载了整个数据集,然后对客户端进行计数,对于大量的数据来说可能非常慢。
Firebase目前没有办法在没有加载数据的情况下对孩子进行计数,但是我们计划添加数据。
现在,一个解决scheme就是维护一个儿童数量的计数器,并在每次添加新的孩子时更新它。 您可以使用事务来计算项目,如在此代码中跟踪upvodes:
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最近发布了云端函数。 使用云function,您不需要创build自己的服务器。 您只需编写JavaScript函数并将其上传到Firebase即可。 每当事件发生时,Firebase将负责触发function。
例如,如果要计数upvotes,则应该创build一个与此类似的结构:
{ "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()); });
您可以阅读文档以了解如何开始使用云function 。
此外,计数职位的其他例子是在这里: https : //github.com/firebase/functions-samples/blob/master/child-count/functions/index.js
保存计数,并使用validation来执行。 我一起黑了 – 为了保持一个独特的票数和计数,不断出现! 但这次我testing了我的build议! (尽pipe有剪切/粘贴错误!)。
这里的“技巧”是使用节点优先级作为投票计数…
数据是:
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()"
用户只能投一次&&计数必须高于当前计数&&数据值必须与优先级相同。
} } ,"count" : { ".validate" : "data.parent().child(newData.val()).val()==newData.getPriority() && newData.getPriority()==data.getPriority()+1 " }
计数(最后的选民真的) – 投票必须存在,其数量等于newcount,&& newcount(优先级)只能上升一个。
} }
testing脚本添加10个不同的用户投票(对于这个例子,id的伪造,应该用户auth.uid在生产中)。 通过(i–)10倒数来查看validation失败。
<script src='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>
这里的“风险”是投票,但计数没有更新(黑客或脚本失败)。 这就是为什么投票有一个独特的“优先” – 脚本应该真正开始,确保没有比当前计数优先的投票,如果有它应该完成自己的事务之前 – 让您的客户清洁为你:)
计数需要在开始之前以优先级进行初始化 – 伪造不会让您这样做,所以需要一个存根脚本(在validation处于活动状态之前!)。
这个游戏有点晚了,其他几个人已经很好地回答了,但我会分享一下我可以实现的方式。
这取决于Firebase REST API提供shallow=true
参数的shallow=true
。
假设你有一个post
对象,每个对象都可以有多个comments
:
{ "posts": { "$postKey": { "comments": { ... } } } }
你显然不想获取所有的评论,只是评论的数量。
假设你有一个post的关键,你可以发送一个GET
请求到https://yourapp.firebaseio.com/posts/[the post key]/comments?shallow=true
。
这将返回键值对的对象,其中每个键是注释的键,其值是true
:
{ "comment1key": true, "comment2key": true, ..., "comment9999key": true }
这个响应的大小要比请求等效数据小得多,现在你可以计算响应中的键的数量来find你的值(例如commentCount = Object.keys(result).length
)。
这可能不能完全解决您的问题,因为您仍然在计算返回的键的数量,并且您不一定会在更改时订阅该值,但这会大大减less返回数据的大小,而不需要对您的任何更改架构。
写一个云function并更新节点数量。
// 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
root– | | -users(此节点包含所有用户列表)|
| -count | -userscount :(该节点通过用户数量dynamic添加该节点)
我很欣赏这是从开放的问题2年,但作为其第一个谷歌的结果,我想我会更新,因为我目前正在寻找一种方法来获得一个对象的儿童数。 这可以用来完成
提供了DataSnapshot.numChildren()方法,更多详细信息可以在这里find – Firebase网站