Standard pattern for searching and displaying documents


#1

Say I have a Meteor site where I want a function to search for a document in a collection and display it to the user.

This collection is very large and is not feasible to keep all on the client.

I have a publish statement that specifies what documents need to be pushed to the user.

Meteor.publish('listing', function (search) {

    return TestObjs.find({"name": search });

});

And I have a search input textbox which when it changes I’d like to subscribe to the publication to get the records that I need.

'change #searchText' : function(e,t){
    Session.set("searchTerm", $("#searchText").val());
    Meteor.subscribe("listing", $("#searchText").val());

}

So every time I search for text, client is getting sent the documents it needs to be displayed.

The problem is, the subscribe call doesn’t delete any old documents from the client for previous search terms. So the first problem is the more the user uses the search function, the more documents are going to be stored on the client. Secondly, if I want to display the search results for the current search term, I cannot just go

Template.home.helpers({
    listOfObjs: function () {
        return TestObjs.find().fetch();
    }
});

This will return all record on the client which would be all records that match the current and any previous search term.

I have to replicate the publish statement

Template.home.helpers({
    listOfObjs: function () {
        return TestObjs.find({"name": Session.get("searchTerm") }).fetch();
    }
});

This works, but I’m essentially duplicating the logic in multiple places. This is just a simple example but what if my search algorithm was more complicated with paging etc.

So I was wondering, what is the recommended Meteor way to return search results for collections that sit on the server?


#2

I got this from SO.

  Simply resubscribing to the publication restarts the subscription.

var subscription = Meteor.subscribe("allplayers");

//later - stop subscription

subscription.stop();


//later - restart subscription

subscription = Meteor.subscribe("allplayers");

Use this on the template.name.event({}) to empty the client minimongo then restart the subscription using another params


#3

Hey @waiholiu I wrote up an article on just this you might find helpful, see here http://meteorcapture.com/simple-search-pattern/


#4

Hi dburles,

Thanks for the article. Just wondering, putting the subscribe call in the autorun, does that mean it’ll automatically stop the subscription or will all the documents from all results remain in the client side database?

Wai


#5

If you’re wanting to avoid that happening you might want to subscribe on the template instance. Something like:

Template.books.onCreated(function() {
  var self = this;
  self.autorun(function() {
    if (Session.get('booksSearchQuery'))
      self.subscribe('booksSearch', Session.get('booksSearchQuery'));
  });
});

that way once the template is destroyed both the autorun and subscription will be stopped.