1

I am currently working on my own project, based on the discover meteor book.

I have subscriptions of my collection 'posts'.

I am using easy-search (a search package), and currently having some troubles.

I have easy search on a overlay called in with javascript.

When I search, it will always return the posts included in the subscriptions + search result as the result.

For example, if I'm in the post lists page, if I search for Chocolate, the result would be every posts in the post list page + chocolate keyword posts.

It goes the same for single post pages.

I was wondering if I could unsubscribe temporarily with a click event. In this case, would be the search button.

Sang Yoo Kim
  • 365
  • 1
  • 15

1 Answers1

4

Don't use Meteor.publish for searching.

  1. Create a Meteor.method on the server instead to find the search results.
  2. Create a client-only (unmanaged) collection var results = new Mongo.Collection(null)
  3. When you perform the search, remove all results results.remove({}) and then insert the results from the Meteor.method callback.

Then, to stop each search waiting until the next one completes (bad for autocomplete), you can look at calling the Meteor.method with wait: false eg.

Meteor.apply('mySearchMethod',[parameters], {wait: false}, function(err, res){});

To make this work, you need to call this.unblock() inside the search method.


Example Code

var searching = new ReactiveVar(false);
var currentSearch = "";
var results = new Mongo.Collection(null);
var search = function(searchText){
  searchText = searchText.trim();
  if (searchText === currentSearch){
     // abort search if query wasn't different
     return;
  }
  // clear results immediately (don't show expired results)
  // NOTE: this can cause "flicker" as results are removed / re added
  results.remove({});
  if (searchText === ""){
     return;
  } 
  searching.set(true);
  performSearch(searchText)
};
var performSearch = _.debounce(function(searchText){
  currentSearch = searchText;
  Meteor.apply('mySearchMethod', [searchText], {wait: false}, function(err, res){
    if (err){
        console.error(err);
    } 
    if (currentSearrch !== searchText){
       // query changed, results aren't relevant
       return;
    }
    for (var i = 0; i < res.length; i++){
       results.insert(res[i]);
    }
    searching.set(false);
  })
}, 300);

Template.myTemplate.events({
  'input #mySearchBox': function(e){
    search($(e.currentTarget).val());
  }
});

Template.myTemplate.heplers({
  'searchResults': function(){
     return results.find();
  },
  'showSpinner': function(){
     return searching.get();
  }
})


if (Meteor.isServer){
  Meteor.methods({
    'mySearchMethod': function(searchText){
         check(searchText, String);
         this.unblock();
         var searchExp = new RegExp(RexExp.escape(searchText), 'i');
         return myCollection.find({myField: searchExp}).fetch();
    }
  });
}
nathan-m
  • 8,875
  • 2
  • 18
  • 29
  • Thank you so much! I just woke up and I feel like I got an early christmas present. I guess I'll have to create my own instead of using a package :) – Sang Yoo Kim Nov 26 '14 at 04:10