I have a collection but don't want to publish it all to client because it's huge, however I need to publish some stats from this collection (as count, sum, avg, etc).
I can't use methods
because they are not reactive and also I can't use publish
because it works only with cursor
.
I have an idea to create additional collection and store these stats in it, but this looks a bit strange.
What the best way to do it?
Solution
On server side:
Meteor.publish('myStats', function() {
var self = this;
var initializing = true;
var stats = {};
var filter = {/* Your filter if needed */};
var calcStats = function() {
stats = {stat1: 0, stat2: 0}; // Init stats
var mc = MyCollection.find(filter).fetch();
for (var i = 0; i < mc.length; i++) {
doc = mc[i];
// Here any logic to calculate stats
stats.stat1 += 1;
stats.stat2 += doc.field;
// ...
}
if (!initializing) {
return self.changed('myStats', 'stringId', stats);
}
};
MyCollection.find(filter).observeChanges({
added: calcStats, // I will recalculate all my stats
changed: calcStats, // after any changes happend
removed: calcStats
});
initializing = false;
this.added('myStats', 'stringId', stats);
return this.ready();
});
Create collection on client side:
MyStats = new Mongo.Collection('myStats');
Use stats:
Meteor.subscribe('myStats');
var stats = MyStats.findOne('stringId');
You can use meteor methods if you like. You simply need to store the results of your meteor method call in a reactive variable, for example, a session variable.
Template.templateName.onRenedered( function() {
Meteor.call("getStats", function(err, res) {
Session.set("count", res.count); // for example
}
});
You can also take a look at the reactive-var package to create your own reactive variables, which you can attach to templates rather than polluting the global session.
Edit: this may not solve your problem of it being not reactive. Take a look at this answer: How to 'transform' data returned via a Meteor.publish?. Here you can change the data you are publishing, mapping your cursor to something less large while adding the fields you need.