如何循环遍历这个数据库并获取子值?

8
我有一个数据库,长这个样子: enter image description here 所以第一个键是从auth获取的用户uid,然后还会取得该用户提供的用户名以及他们每场比赛的得分。
我只想获得每个用户的总得分 - 例如Ray的总分是45,Wood的总分是44,但是在查阅了文档之后,我只能为一个用户计算,必须为每一行编写每个用户名和特定比赛来获取值。现在想象一下,如果有几十个用户会怎么样?好多行啊。
这是JSON链接: JSON JavaScript代码:
var query = firebase.database().ref();
 query.once("value")
 .then(function(snapshot) {
 snapshot.forEach(function(childSnapshot) {

  var key = childSnapshot.key;      
  var Data1 = childSnapshot.child("Ray/Match1/Points").val();
  var Data2 = childSnapshot.child("Ray/Match2/Points").val();
  console.log(Data1 + Data2);
  });
 })

我希望能够显示Ray的总分数,但显然不能包括Wood的分数。我该如何解决这个问题?


这是一种问题类型,Firebase云函数在所有其他前端实现中都表现出色。 - Emeka Obianom
4个回答

6
我查看了你的问题,我认为我已经找到了解决方案,或者至少是一个迈向解决方案的途径。首先我将解释基本问题,然后尝试提供一些通用的代码(我将尝试使用一些您使用的变量)。来吧,我们开始吧!
基本上,我看到的是两个步骤...
第一步 - 您需要使用“构造函数”,它将创建新的用户对象,具有自己的名称(和/或用户ID)和自己的属性集。
有了这种思路,您可以使构造函数包含诸如“用户名”、“匹配点数1”、“匹配点数2”等属性,然后再添加一个函数,用于在控制台记录每个名称以及他们从匹配点1和2获得的总点数的摘要。
第二步 - 您需要将构造函数放入一个循环中,该循环将遍历数据库,寻找需要填充构造函数所需属性的特定属性,以便输出您要查找的信息。
因此...让我们深呼吸一下,因为那是很多话......让我们尝试编写代码。我将使用通用属性的方式,我认为这样做可以让您轻松插入自己的属性/变量名称。
var user = function(name, match1, match2){
    this.name = name;
    this.match1 = match1;
    this.match2 = match2;
    this.pointTotal = function(match1, match2) {
        console.log(match1 + match2);};
    this.summary = function(){
            console.log(name + " has a total of " + pointTotal + " 
points.");};
}

这段代码中的"This"部分允许使用任何用户名,而不仅限于特定的用户名。
好的,所以上面的代码解决了构造函数部分的问题。现在无论需要创建多少个具有唯一名称的用户都没有问题了。
下一步是创建某种循环函数,该函数将遍历数据库并填充创建每个用户所需的属性,以便可以从每个用户获取总积分,而不仅仅是一个用户。
同样,我将使用通用的属性/变量名称......
var key = childSnapshot.key;

while(i = 0; i < key.length + 1; i++) {

    var user = function(name, match1, match2){
        this.name = name;
        this.match1 = match1;
        this.match2 = match2;
        this.pointTotal = function(match1, match2) {
            console.log(match1 + match2);};
        this.summary = function(){
            console.log(name + " has a total of " + pointTotal + " points.");};
    }
}

这是一大堆话,代码是通用属性名称/变量和你使用的属性名称/变量的混合,但我确信我走在正确的道路上。

我非常有信心,如果您使用我提供的代码和解释,并插入您自己的变量,您将得到所需的解决方案。

最后,我只想说我真的希望这可以帮到您,如果不能,我愿意以任何方式帮助解决问题,因为我需要练习。我有一个怪异工作时间的工作,所以如果我没有立即回答,很可能是在工作中 :(

祝您好运,希望我有所帮助!


看起来Mohammed比我更快地找到了一个简单得多的解决方案!我将反向工程他的答案,以便我可以理解它。嘿...BRAVO Mohamed! :) - Shenole Latimer
感谢您抽出时间编写此内容,您能给我展示一个JSON的例子吗?您是指像这样的吗:https://jsonblob.com/f22313a3-4e29-11e7-ae4c-096d61fc72e0 - skyline33
嘿,Skyline!不幸的是,我很抱歉地说我还不了解JSON的基础知识。我只知道HTML、CSS和JavaScript,但我对JavaScript已经非常熟悉,并且认识到你问题中的JavaScript,看到它可以被解决。 - Shenole Latimer

5

只需向您的数据库添加 total 节点即可。

|_Id
   |_ $userId:
   |       |_ Ray
   |       |    |_ Match1:24
   |       |    |_ Match2:21
   |       |_ total:45

然后获取用户的总数

var query = firebase.database().ref();
 query.once("value")
 .then(function(snapshot) {
 snapshot.forEach(function(childSnapshot) {
  var total = childSnapshot.child("total").val();
  console.log(total);
  });
 })

您可以使用云函数添加总节点


1
很棒的回答,Mohamed。不过我会做出一些改变,将总分数与比赛结果分开存储,这样您就可以检索所有用户的总分数。因此,/TotalScores/$uid/45 - Frank van Puffelen
这是唯一的方式吗?只能通过云函数实现吗?我只想建立一个简单的静态网站,难道没有其他方法吗? - skyline33
总有几种方法可以解决你的问题。但我认为在后端实现你的逻辑更方便(在你的情况下是一个简单的Node函数)。或者,每次保存比赛到数据库时,你也可以给总分数加上相应的分数。 - Mohamed Hesham
似乎为了仅显示总积分而通过节点和那些东西进行大量工作...如果没有其他方法,我现在可能会看看PHP / MySql。 - skyline33
随着您的应用程序变得越来越大,将逻辑后端保持在服务器上可以更加高效和安全。最终决策取决于您自己。 - Mohamed Hesham
@skyline33 这可以说是最佳的方法。此外,逻辑位于服务器端,而不是前端。因此,您可以进行逻辑更改,而无需更新前端。 - Moses Aprico

3
请查看这个实现。无需云函数。
 firebase().database().ref().on('value', function(snapshot) {
 snapshot.forEach((user)=>{

  user.forEach((matches)=> {
     var total = 0;
     matches.forEach((match)=> {       
         total += match.val().Points;          
     }); 
     console.log(total);                         
   });    

  });
 })

1
虽然这是正确的,但不是最优的,因为你需要在前端循环。Mohamed的方法更好,因为它将逻辑隐藏在应用程序中(更安全)。此外,Firebase是一个NoSQL数据库。因此,从NoSQL的角度来看,这将是更优的解决方案。 - Moses Aprico

1
如果键是用户的ID,为什么还要添加一个嵌套对象来存储用户的姓名?您是否期望一个用户有多个用户名?这听起来很奇怪并增加了复杂性,正如您可能已经注意到的那样。如果您需要在Firebase中保存用户名,则建议您在用户ID键直接下面专门创建一个用户详细信息部分。以下是Firebase对象结构的JavaScript表示形式:
{
  a1230scfkls1240: {
    userinfo: {
      username: 'Joe'
    },
    matches: {
      asflk12405: {
        points: 123
      },
      isdf534853: {
        points: 345
      }
    }
  }
}

现在,获取总积分似乎更加直接了当,不是吗?
为了帮助您而不修改当前的数据库结构,您只需要循环遍历数据库中所有的userId+username+matches排列组合。以下是一个示例代码,可以实现这一点,您不需要任何特殊的Firebase功能,只需使用好老式的JavaScript for-of循环即可:
const query = firebase.database().ref();

query.once('value')
.then(snapshot => {
  const points = {}
  const users = snapshot.val()

  for (const userId of Object.keys(users)) {
    const userprofile = users[userId]

    for (const username of Object.keys(userprofile)) {
      const user = userprofile[username]

      for (const matchId of Object.keys(user)) {
        const match = user[matchId]
        // Store the points per user, per profile, or per both, depending on your needs
        points[username] = points[username] === undefined
          ? points[username] = match.points
          : points[username] += match.points
      }
    }
  }
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接