使用函数在Firebase数据库中对节点的子节点进行排序

时间:2017-04-12 13:03:02

标签: node.js firebase firebase-realtime-database

我在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功能

1 个答案:

答案 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。它可以而且应该被优化,这个解决方案只是一个很好的起点。