4

Counting records in a table is obviously a manual effort until you guys get some of that spiffy new functionality already in the works ;)

However, I'm stuck on even using a manual run with .on('value', ...) to fetch a count:

var table = new Firebase('http://beta.firebase.com/user/tablename');
var count = 0;
table.on('child_added', function(snapshot) {
   count++;
   // how do I know if this is the last child? i.e. the count is complete?
});

// when is it okay to use count?

I foresee the same issues with any sort of pagination and I feel like I'm being a bit blockheaded about this. What am I missing?

Is this fundamentally the wrong pattern for, say, getting the number of messages a user has in his/her queue?

Kato
  • 40,352
  • 6
  • 119
  • 149
  • Try this Use javascript object count, it work. http://stackoverflow.com/questions/5223/length-of-a-javascript-object – wwin3286tw Nov 27 '16 at 17:08

3 Answers3

7

The child_added event has no notion of "done", since children can continue to be added over time. If you want to get a count of the children right now, you can use 'value' to get the current snapshot from that location and then count the children. For example:

table.once('value', function(snapshot) {
  var count = 0;
  snapshot.forEach(function(childSnapshot) {
    count++;
  });
  // do something with count.
});

Alternatively, if you want the count to continually update, you can use .on() instead of .once() above. But this isn't ideal performance-wise, since you'll be counting all of the children every time. Fortunately, you can use a combination of 'child_added' and 'value' to efficiently keep a count:

var count = 0;
table.on('child_added', function(snapshot) {
  count++;
  // how do I know if this is the last child? i.e. the count is complete?
});

table.on('value', function(snapshot) {
  // do something with count.
});

This works since 'value' will fire once after the "initial" data is complete and then again whenever the data changes, so you'll get a continually updating correct count. Though you'll need to handle child_removed as well if you expect children to be removed.

Michael Lehenbauer
  • 16,229
  • 1
  • 57
  • 59
  • Right, for some reason I forgot about getting the snapshot and using forEach after our discussion about the overhead involved in calling `value` on the parent table. What my brain heard: "delete value/forEach from memory" :( See? I knew it was obvious. – Kato Jul 23 '12 at 19:42
  • Haha. Well, glad it makes sense now. :-) – Michael Lehenbauer Jul 23 '12 at 20:54
6

With "child_added" there is no way to know when you've received the "last" item. If you're looking to count all of the children that existed at a particular point in time, I'd suggest using the "value" event as follows:

var table = new Firebase('http://beta.firebase.com/user/tablename');

table.on('value', function(snapshot) {
   var count = 0;
   snapshot.forEach(function() {
       count++;
   });
   //count is now safe to use.
});
Andrew Lee
  • 10,127
  • 3
  • 46
  • 40
  • Yeah, being blockheaded. I had discounted using `forEach` because it requires calling `value` on the parent, which can be a large overhead on big tables. Somewhere, I slipped it entirely. :) – Kato Jul 23 '12 at 19:41
0

Until FB implements count as a returned function, I guess the best way to not have client side loop through any returned records is to fetch it the REST way.

ref: What’s the best RESTful method to return total number of items in an object?

Community
  • 1
  • 1
killjoy
  • 940
  • 1
  • 11
  • 16