2017-04-01 65 views
1

对于每个用户帐户,我试图计算他们今天有多少事件。如何计算符合特定条件的Firebase子项目

accounts - 
{ 
"-KaxcGWx1-a8s7dhsjhsd" : { 
"name" : "Bill", 
"events" : [ { 
    "event" : "-KdHscYor4mA--ubIHBj" 
}, { 
    "event" : "-KdKsJBdHimgPPQQ6bcA" 
} ], 
}, 
"-KaxcGWx1-rA2anjKI4h" : { 
"name" : "Bob", 
"username" : "Bob" 
"events" : [ { 
    "event" : "-KdHscYor4mA--ubIHBj" 
}] 
} 
} 


events - 
{ 
"-KdHscYor4mA--ubIHBj" : { 
    "dateCreated" : "Fri Feb 17 2017 23:37:32 GMT+0000 (GMT)", 
    "eventDate" : "2017-04-01", 
    "name" : "Event 1", 
}, 
"-KdKsJBdHimgPPQQ6bcA" : { 
    "dateCreated" : "Fri Feb 17 2017 23:37:32 GMT+0000 (GMT)", 
    "eventDate" : "2017-04-01", 
    "name" : "Event 2", 
} 
} 

所以考虑到这两个事件对今天:

我的数据结构如下。我希望比尔有两个,鲍勃有一个。

我已经尝试的代码是:

var todayDate = '2017-04-01'; 
var ref = firebase.database().ref('accounts/'); 
ref.once('value', function (snapshot) { 
    //Foreach user account 
    var eventCount = 0; 
    snapshot.forEach(function (account) { 
     var ref = firebase.database().ref('accounts/' + account.key); 
     ref.child('events').once('value', function (eventSnapshot) { 
      //Foreach event 
      eventSnapshot.forEach(function (child) { 
       firebase.database().ref('events/' + child.val().event).once('value', function (event) { 
         if (eventDate === todayDate) { 
          console.log(account.val().name, 'has an event today -', event.val().name); 
          eventCount++; 
         } 
       }); 
      });  
     }); 
     console.log(account.val().name, 'total events -', eventCount); 
    }); 
}); 

但是,我越来越控制台的结果是:

Bill total events - 0 
Bob total events - 0 
Bill has an event today Event 1 
Bill has an event today Event 2 
Bob has an event today Event 2 
+0

您显示的数据结构中没有什么是日期。请添加实际的JSON(作为文本),您可以通过点击[Firebase数据库控制台](https://console.firebase.google.com/project/_/database/data/)中的导出JSON来获取JSON。还要确保你的代码片段是完全独立的。现在,我们无法知道“todayDate”和“eventDate”是什么。在一个小型的jsbin中重现问题,然后将其与您的问题联系起来可能是一个好主意。 –

+0

eventDate是任意的。我简化了我的示例代码,但我会尝试获取jsbin示例。日期匹配工作正常。问题似乎是在snapshot.forEach完成之前触发了回调。这似乎是控制台以明显错误的顺序记录事件的原因 – MNelmes

+0

您是否将帐户名称用作密钥? – adolfosrs

回答

0

的问题是你的代码的总体结构。你深深地嵌套了对ref.once('value')的调用,并期望它们全部同步执行。但是,once()是异步的。该函数总是立即返回 - 它不会等待快照。过一段时间,只要数据可用,您的回调就会与快照一起被调用。这意味着您的foreach循环会迭代快照的每个子节点并在调用任何快照回调之前完成。结果是你的计数为0.

你将需要以事件驱动的异步方式完全重构你的代码,而不是你现在使用的程序同步方式。

+0

谢谢,这是有道理的。我试图找出Firebase的承诺和回调,但仍然迷失方向。 https://firebase.googleblog.com/2016/01/keeping-our-promises-and-callbacks_76.html – MNelmes

+0

是的,您的代码可以使用承诺更容易理解的方式构建。在处理的每个阶段,对一系列promise作出“then”()方法的“连锁”调用是很常见的。 –

0

使用您当前的结构,缩放时会遇到问题,因为您需要检索所有用户,然后检索该用户的所有时间事件并检查每个日期。通过稍微改变你的事件数据结构,你可以简单得多。

events: { 
    eventId1: { 
    date: '20170401', 
    attendingAccount:{ 
    accountId1: true, 
    accountId2: true, 
    } 
    }, 
    eventId2: {...} 
} 

如果你只是保存正参加像上面你只需要运行类似事件的用户accountId如下:

let attendingCount = {}; 

firebase.database().ref('events').orderByChild('date').equalTo(today).once(snap => { 
    let events = snap.val(); 

    if (events){ 
     Object.keys(events).forEach(eventId => { 
      Object.keys(events[eventId].attendingAccounts).forEach(accountId => { 
       if (!attendingCount[accountId]){ 
        attendingCount[accountId] = 0; 
       } 
       attendingCount[accountId]++; 
      }); 
     }); 
    } 
}); 

这将导致该对象attendingCount具有计算每个accountIds。

attendingCount: { 
    accountId1: 2, 
    accountId2: 5, 
    ... 
}