如何计算符合特定条件的Firebase子项

时间:2017-04-01 21:25:17

标签: javascript firebase firebase-realtime-database

对于每个用户帐户,我试图计算他们今天有多少事件。

我的数据结构如下:

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

2 个答案:

答案 0 :(得分:0)

问题在于代码的一般结构。您已经深入嵌入了对ref.once(' value')的调用,并期望它们全部同步执行。但是,once()是异步的。该函数总是立即返回 - 它不会等待快照。稍后,只要数据可用,就会使用快照调用回调。这意味着您的foreach循环正在迭代快照的每个子节点,并在调用任何快照回调之前完成。这导致你的计数为0。

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

答案 1 :(得分: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,
   ...
}