我在firebase数据库中有一个排行榜。我为得分和userName设置了.indexOn
规则。我添加了记录,进入前十名,这些记录很快,很容易在客户端实现。
但检索当前用户的排名可能会在客户端变得非常慢,因为我必须获取排行榜节点的子项的完整列表并计算记录,直到找到用户记录...此排行榜可以获得高达100k的记录。更不用说这会带来巨大的网络流量。
我想使用firebase函数在插入记录时对记录进行排序和排名,这样我就可以保持网络流量尽可能低。
我的结构是这样的:
"leaderboard": {
"user_id_xxxx":
{
"uid": "user_id_xxxx",
"userName" : "someone",
"score": 99999
"rank": 1
},
"user_id_xxxy":
{
"uid": "user_id_xxxy",
"userName" : "otherone",
"score": 99998
"rank": 2
}
}
所以我提出了一个代码段,但我不知道如何订购它:
var functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var dbRef = functions.database.ref('/leaderboard');
exports.dbRefOnWriteEvent = dbRef.onWrite(event => {
const parentRef = event.data.ref.parent();
return parentRef.once('value').then(snapshot => {
var i = 1;
const updates = {};
snapshot.forEach(function(child) {
child.rank = i;
i++;
});
return parentRef.update(updates);
});
});
我感谢任何建议和帮助,我还在学习node.js和Firebase功能
答案 0 :(得分:0)
好的,我明白了。下面的代码是第一个可行的解决方案。
var functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var dbRef = functions.database.ref('/leaderboard');
exports.dbRefOnWriteEvent = dbRef.onWrite(event => {
var ref = admin.database().ref("/leaderboard");
ref.orderByChild("score").once("value", function(dataSnapshot) {
var i = 0;
dataSnapshot.forEach(function(childSnapshot) {
var childRef = childSnapshot.ref;
var r = (dataSnapshot.numChildren() - i);
childRef.update({rank: r},function(error) {
if (error != null)
console.log("update error: " + error);
});
i++;
});
});
});
您必须设置这样的索引规则才能使其正常工作:
"leaderboard": {
".indexOn": [ "/score", "/rank" ]
}
不确定为什么它需要斜线字符,没有它就无法工作。
简短说明:我在排行榜中添加了onWrite
触发器,每次更新时forEach
都会运行并更新rank
。它可以而且应该被优化,这个解决方案只是一个很好的起点。