Realtime counts in Meteor — Different approaches by example
Counting data is one of the things a programmer does on a regular basis.
“How many customers are currently on the page?”, “How many offers are displayed for this search result?”, “How often was this product sold?”.
Those are just some of the questions which may arise when developing modern web applications.
Implementing a (real time) counting mechanism in Meteor isn’t that easy.
This blog post will discuss different approaches which will show you how you can do just that.
We’ll show some example source code you could use and discuss up- and downsides for each approach.
Let’s start
Method based counts
The first method I’ll show you is the method based count implementation.
The idea is to implement a method on the server side which calculates the current count. You’ll then just call the method from the client side every X seconds (this is not quite real time, but based on the interval you execute the method you can make it as nearly as realtime).
Example
// the method on the server<br />
Meteor.methods({<br />
postsCount: function () {<br />
let postsCount = Posts.find().count()<br />
return postsCount;<br />
}<br />
});<br />// fetch the data on the client (every 30 seconds)<br />
Meteor.setInterval((function () {<br />
Meteor.call('postsCount', function(error, result) {<br />
// store the returned value in e.g. a session variable<br />
Session.set('postsCount', result);<br />
});<br />
}), 30000);<br />
Upsides
- You can choose when the data should update
Downsides
- Cumbersome processing of received data
- Not real time
Overpublishing
Overpublishing means that you publish all the documents down the wire and do the computation on the client side.
Example
// the publication on the server (publish every post)<br />
Meteor.publish('posts', function () {<br />
return Posts.find();<br />// on the client<br />
let postsCount = Posts.find().count()<br />
Upsides
- Only a few lines of code are needed
- Meteoric implementation (doesn’t feel like a hack)
- Overpublished data might be reused
Downsides
- Slow when dealing with huge amount of data
- Too much data is transferred (even if you use the fields property to filter which will be sent to the clients)
Custom publications
In this approach we’ll use the possibility to create a custom publication which will calculate the count of the documents on the server and publish this count into a custom ‘counts’ collection. This idea might sound a little bit cumbersome and not easy to understand, but when you see the source code you’ll see that it’s fairly easy.
Example
// the custom publication on the server<br />
Meteor.publish('postsCount', function () {<br />
let subscription = this;<br />
let postsCount = Posts.find().count();</p>
<p> let countObject = {};<br />
countObject.postsCount = postsCount;<br />
countObject.type = 'post'; // should be added because all your counts will be contained in one collection</p>
<p> subscription.added('counts', Random.id(), countObject);<br />
subscription.ready();<br />
});<br />// on the client<br />
// the collection (is one place to store all counts)<br />
Counts = new Mongo.Collection('counts');</p>
<p>// getting the count data<br />
Meteor.subscribe('postsCount');<br />
let postsCount = Counts.findOne({ type: 'post' }).postsCount;<br />
Upsides
- You can modify the data in your publication (e.g. aggregate related data into one count)
- Reusable counts collection
Downsides
- Extra package such as reactive mongo needed to make it reactive
- Unpredictable performance when a reactive publish package is added
Publish counts package
At the end we’ll take a look at a package which will help you with the real time counting problem. It’s called Publish counts and was developed by the guys from Percolate.
Example
# on the command line<br />
meteor add tmeasday:publish-counts<br />// the publication on the client<br />
Meteor.publish('posts', function() {<br />
Counts.publish(this, 'postsCount', Posts.find());<br />
});<br /><br />
Meteor.subscribe('posts');</p>
<p>postsCount = Counts.get('postsCount');<br />
Upsides
- Can be embedded into an already defined publication
- Easy to use API
Downsides
- Slow performance when dealing with lots of data
Conclusion
There are many different ways available to count documents in Meteor and enable a real time way to do those computations. Unfortunately there is no silver bullet solution available right now. But based on your requirements you can pick one of the solutions above to add real time counts to your application.