Meteor filtered publication with limit and skip with total count

216 Views Asked by At

Given a filtered and paginated meteor publication, how do I get the total count with the filtered applied?

Client Code:

import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { Track } from 'meteor/tracker';

import { Posts } from '/imports/api/posts/posts.js';

import './posts.html';

Template.App_posts.onCreated(function() {
  this.subscribe('posts.all', new Date(), 0);

  Tracker.autorun(() => {
    let postCount = Posts.find({}).count();
    console.log(postCount); // 10
  });
});

Server Code:

import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';

import { Posts } from '../posts.js';

const postsPerPage = 10;

Meteor.publish('posts.all', function(date, page = 0) {
  if (!Meteor.userId()) throw new Meteor.Error('Unauthorised');

  check(date, Date);
  check(page, Number);

  let query = {
    userId: Meteor.userId()
  };

  let options = {};

  if (date) {
    query.createdAt = date;
  }

  options.limit = postsPerPage;
  options.skip = page * postsPerPage;

  let cursor = Posts.find(query, options);

  console.log(cursor.count()); // 100

  return cursor;
});

This returns the expected posts given the date and the page but the problem is knowing the total filtered count.

Assuming there is 1000 posts, 100 of them are applicable for this date and user. How do I get the count of 100 when only 10 are returned at a time?

1

There are 1 best solutions below

9
ivan133 On BEST ANSWER

I think you should use tmeasday:publish-counts https://github.com/percolatestudio/publish-counts

On the server, you should do:

Meteor.publish('posts.numberOfPosts', function(date) {
   if (!this.userId){
       return this.ready();
   } 
   check(date, Date);

   let query = {
      userId: this.userId
   };
   if (date) {
     query.createdAt = date;
   }
   Counts.publish(this, 'all-posts', Posts.find(query));
}

And on the client: Counts.get('All-orders')

Actually, you also may place this subscription inside "posts.all":

Meteor.publish('posts.all', function(date, page = 0) {
  if (!Meteor.userId()) throw new Meteor.Error('Unauthorised');

  check(date, Date);
  check(page, Number);

  let query = {
    userId: Meteor.userId()
  };

  let options = {};

  if (date) {
    query.createdAt = date;
  }

  options.limit = postsPerPage;
  options.skip = page * postsPerPage;

  let cursor = Posts.find(query, options);
  // https://github.com/percolatestudio/publish-counts#noready
  Counts.publish(this, 'all-posts', Posts.find(query), {noReady: true});

  return cursor;
});