I'd like to display a feed of items from various collections, sorted by creation date but i'm facing some problems.
Desired result
- Items from all collections should be mixed on the same page, sorted by date
- The display must stay reactive
- I use jQuery Isotope for the layout
- The result set is limited (10 first items for example) and a 'load more' button can be clicked to expand the query limit
I can't limit the result set correctly
As each collection must be queried separately, the best I can do is get the 10 first items for each collection.
In the illustration below, the desired result set is in red and the green outlines are the ones I get.
Currently, I fetch the three cursors, merge in one array, sort and keep the first ten.
Loading more content
When the 'load more' button is clicked, a reactive variable is updated, which is used in the subscription to limit the results for each queries.
That logic of loading too much data every time feels very wrong. What would be the performance impact for a page that would query 3000 elements, sort them in an array, and display only the 1000 first.
I may overlooked a very simple way to do it. I'm sure that some brilliant minds here can help me find a better approach.
Some code
Limited to two collections to make it a bit more concise
// Server
Meteor.publish('allContent', function(limit) {
return [
Posts.find({}, {limit: limit}),
Articles.find({}, {limit: limit})
];
});
// Client
Template.home.onCreated(function () {
var instance = this;
// initialize the reactive variables
instance.loaded = new ReactiveVar(0);
instance.limit = new ReactiveVar(10);
instance.autorun(function () {
// get the limit
var limit = instance.limit.get();
// subscribe to the posts publication
var subscription = instance.subscribe('allContent', limit);
// if subscription is ready, set limit to newLimit
if (subscription.ready()) {
instance.loaded.set(limit);
}
});
instance.content = function() {
var llimit = instance.loaded.get();
var posts_cursor = Posts.find({}, {limit: llimit});
var articles_cursor = Articles.find({}, {limit: llimit});
var posts_docs = posts_cursor.fetch();
var articles_docs = articles_cursor.fetch();
var docs = posts_docs.concat(articles_docs);
var mix = _.sortBy(docs, function(doc) {return doc.created_at;}).reverse().slice(0,Session.get('limit'));
// Pass the cursors to observe them and re-layout isotope when necessary
return {items: mix, cursors: [services_cursor, posts_cursor]};
}