2

Is it better to store a counter and update it transactionally in realtime every time it is changed or compute it from each possible data source?

For example: I am building an app that tracks "checkins", similar to FourSquare. When the user "checks in" to a location I need to track the stats for the individual AND the total for the location over all users. (This is a simplified version of the app for brevity purposes, the real app tracks much more information).

For example Joe checks into Coffee Place:

  • Joe/CoffeePlace/+1

Now Fred, Tom and Lisa also check into the Coffee Place:

  • Fred/CoffeePlace/+1
  • Tom/CoffeePlace/+1
  • Lisa/CoffeePlace/+1

The above is necessary to track for the individuals but the best practice for tracking total number of check-ins at Coffee Place is unclear to me.

Which is the right approach?

  1. Gather data from each user node and then compute all checkins -> display total check ins
  2. Create a file for Coffee Place that updates at each check in like: CoffeePlace/+1+1+1+1

I would imagine for very large datasets that computationally would be time consuming (not because of the computation but because of gathering the data from each node). What is best practice here?

Community
  • 1
  • 1
Abhi
  • 270
  • 3
  • 12

1 Answers1

2

In Firebase (and most NoSQL databases) you often store the data for the way that your application consumes it.

So if you are trying to track the number of check-ins at a place, then you should at the very least track the check-ins for each place.

PlaceCheckins
  CoffeePlace
    Fred: true
    Tom: true
    Lisa: true

If you also want to show the places where a specific user has checked in, you'll keep the same data per user (as you already had).

UserCheckins
  Fred: 
    CoffeePlace: true
  Tom: 
    CoffeePlace: true
  Lisa: 
    CoffeePlace: true

This type of data duplication is very normal in Firebase (and again: NoSQL databases in general). Disk space is cheap, the user's time is not. By duplicating the data, you ensure that you can get exactly what you need for a specific screen in your app.

To keep both lists in sync, you'd use multi-location updates or transactions (depending a bit on how you structure the data). A checkin by Jenny into the coffee place could be coded in JavaScript as:

var updates = {};
updates['/PlaceCheckins/CoffeePlace/Jenny'] = true;
updates['/UserCheckins/Jenny/CoffeePlace'] = true;
ref.update(updates);

If you also want to display the count of check-ins (for a specific user of a specific place), you either download the check-ins and tally client-side or you keep a total in the database. If you take the latter approach, have a look at my answer on Is the way the Firebase database quickstart handles counts secure?

Finally: read this article for a great (non-Firebase specific) introduction to NoSQL data modeling.

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807