简体   繁体   English

如何使用云函数对 Firebase 实时数据库、Node.js 和 Javascript 进行排序和过滤以获得“高分”排行榜

[英]How to Sort and Filter Firebase Realtime Database with Cloud Functions, Node.js & Javascript for 'High Score' Leaderboard

I've been researching and doing trial & error for days but haven't been able to get anything working.几天来我一直在研究和试错,但没有任何工作。 In testing, I created a few test nodes in my Firebase Realtime database in order to try to work out the function's logic.在测试中,我在我的 Firebase 实时数据库中创建了一些测试节点,以尝试计算函数的逻辑。 My file tree looks like this:我的文件树如下所示:

在此处输入图像描述

In simply trying to get the basics working, I created a few users under the TestUsers node that each have a very simple child structure of Statistics and then an orbs value.为了简单地让基础工作正常,我在TestUsers节点下创建了几个用户,每个用户都有一个非常简单的Statistics子结构,然后是一个orbs值。

What I'm trying to do:我正在尝试做的事情:

Upon updating the orbs value under any of the users, I want to write (well, technically 'update') the Output/firstPlace children to include the username and the number of orbs for the top 3 users (that have the highest orb count out of all the users under TestUsers .在更新任何用户下的orbs值后,我想编写(嗯,技术上“更新”) Output/firstPlace子项,以包括前 3 名用户(具有最高 orb 计数的用户名和球体数量) TestUsers下的所有用户。

Seems super simple, and trust me, I know there's tons of documentation out there on sorting and filtering Firebase Realtime Database data but I haven't been able to piece this together from days of reading this documentation.看起来超级简单,相信我,我知道有大量关于排序和过滤 Firebase 实时数据库数据的文档,但是从阅读本文档的几天来看,我一直无法将它们拼凑在一起。

I'm using VS Code to write my functions and am deploying them to my Firebase project.我正在使用 VS Code 编写我的函数并将它们部署到我的 Firebase 项目中。

The function I've written to try to do the above is this:我写的 function 尝试执行上述操作是这样的:

//Define a new function with a base path and set it to run when a child of this path is changed
exports.testTopPlayers1 = functions.database.ref('/TestUsers/{user}/Statistics').onUpdate(_ => { 

    var allPlayersRef = admin.database().ref('/TestUsers/{user}'); //When this function runs, assign a new path of all users

        //Get a snapshot of the top 3 users with the highest orb count
        allPlayersRef.orderByChild('orbs').limitToLast(3).once('value', (snap) => { 

          //For each child from the above snap (should be 3)...
          snap.forEach((child, context) => {

                const username = context.params.user; //Assign the username to a const
                const afterOrbAmount = child.after.val();
                const orbAmount = afterOrbAmount.orbs; //Assign the number of orbs to a const

                //Return (Promise?) by updating the data in '/Output/firstPlace' with the username and orb amount.
                return admin.database().ref('/Output/firstPlace').update({[username]: [orbAmount]});
          });
  })
})

I would expect that with .forEach , it should run the writing to '/Output/firstPlace portion 3 times, effectively giving me 3 new key-value pairs.我希望使用.forEach ,它应该运行写入'/Output/firstPlace部分 3 次,有效地给我 3 个新的键值对。 But nothing happens.但什么也没有发生。

Based on what I'm trying to do, can you either correct my code or show me the proper way to achieve sorting high scores like this on the backend?根据我正在尝试做的事情,您能否更正我的代码或向我展示在后端实现这样的高分排序的正确方法?

You're not returning anything from the top level of your code, which means Cloud Functions has no way to know when your code is done.您不会从代码的顶层返回任何内容,这意味着 Cloud Functions 无法知道您的代码何时完成。 Hence: it stop your code after the last } , which is before the database read has been completed.因此:它在最后一个}之后停止您的代码,这是在数据库读取完成之前。

Your code should look something like this:您的代码应如下所示:

exports.testTopPlayers1 = functions.database.ref('/TestUsers/{user}/Statistics').onUpdate(_ => { 

    var allPlayersRef = admin.database().ref('/TestUsers/{user}'); //When this function runs, assign a new path of all users

    let query = allPlayersRef.orderByChild('orbs').limitToLast(3)
    return query.once('value').then((snap) => { 
        let promises = [];
        snap.forEach((child, context) => {
            const username = context.params.user;
            const afterOrbAmount = child.after.val();
            const orbAmount = afterOrbAmount.orbs;

            promises.push(admin.database().ref('/Output/firstPlace').update({[username]: [orbAmount]}));

        });
        return Promise.all(promises);
    })
})

There may be more problems in your code, but this ensures that your Cloud Function will keep running until the query and the subsequent updates have completed.您的代码中可能存在更多问题,但这可确保您的 Cloud Function 将继续运行,直到查询和后续更新完成。

I highly recommend studying the follow to learn more about how to control when a Cloud Function terminates:我强烈建议您学习以下内容,以了解有关如何控制 Cloud Function 何时终止的更多信息:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM