Why am I getting an error when I try to use the Meteor search package?

I followed this tutorial on the meteor search source and modified the example to fit my current needs. This is my collections.js which is in my lib directory

 Guides = new Mongo.Collection("guides"); 

I have code in the client side controller.

 var options = { keepHistory: 1000 * 60 * 5, localSearch: true }; var fields = ['title']; GuideSearch = new SearchSource('guides', fields, options); Template.guide_list.helpers({ getGuides: function () { return GuideSearch.getData({ transform: function (matchText, regExp) { return matchText.replace(regExp, "<b>$&</b>") } }); }, isLoading: function () { return GuideSearch.getStatus().loading; } }); Template.guide_list.events({ "keyup #title": _.throttle(function(e) { var text = $(e.target).val().trim(); GuideSearch.search(text); }, 200) }); 

And it's like my server side code

 SearchSource.defineSource('guides', function(searchText, options) { if(searchText) { var regExp = buildRegExp(searchText); var selector = {title: regExp} return Guides.find(selector, options).fetch(); } else { return Guides.find({}, options).fetch(); } }); function buildRegExp(searchText) { // this is a dumb implementation var parts = searchText.trim().split(/[ \-\:]+/); return new RegExp("(" + parts.join('|') + ")", "ig"); } 

For some reason, I get the following error message when I type something in the input field

 Exception in delivering result of invoking 'search.source': Meteor.makeErrorType/ errorClass@http ://10.0.3.162:3000/packages/meteor.js?9730f4ff059088b3f7f14c0672d155218a1802d4:525:15 ._livedata_result@http ://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:4625:23 Connection/ onMessage@http ://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:3365:7 ._launchConnection/self.socket.onmessage/<@http://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:2734:11 _.forEach@http ://10.0.3.162:3000/packages/underscore.js?46eaedbdeb6e71c82af1b16f51c7da4127d6f285:149:7 ._launchConnection/ self.socket.onmessage@http ://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:2733:9 REventTarget.prototype.dispatchEvent@http ://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:173:9 SockJS.prototype._dispatchMessage@http ://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:1158:5 SockJS.prototype._didMessage@http ://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:1216:13 SockJS.websocket/ that.ws.onmessage@http ://10.0.3.162:3000/packages/ddp-client.js?250b63e6c919c5383a0511ee4efbf42bb70a650f:1363:9 

This is my template code:

 template(name="guide_list") .format-properly .container-fluid .input-group#adv-search .form-horizontal(role="form" method="POST" action="#") .col-md-6 .form-group label(for="contain") Guide title input.form-control(type="text" id="title") .col-md-6 .form-group label(for="contain") Author input.form-control(type="text" name="author") .col-md-6 .form-group label(for="hero") Select a hero select.form-control(name="hero") option(value="all" selected) All Heroes option(value="Druid") Druid option(value="Hunter") Hunter option(value="Mage") Mage option(value="Paladin") Paladin option(value="Priest") Priest option(value="Rogue") Rogue option(value="Shaman") Shaman option(value="Warlock") Warlock option(value="Warrior") Warrior .col-md-6 .form-group label(for="filter") Filter by select.form-control(name="filterBy") option(value="0" selected) All guides option(value="most_viewed") Most viewed option(value="top_rated") Top rated option(value="most_commented") Most commented .container-fluid .table-responsive table.table.table-hover thead tr th hero th title th author th updated th dust th span.glyphicon.glyphicon-eye-open th span.glyphicon.glyphicon-heart th span.glyphicon.glyphicon-comment tbody each guides tr td {{hero}} td a(href="/guide/{{formatId _id}}") {{title}} td {{authorUsername}} td {{moFormat modifiedAt 'YYYY-MM-DD'}} td {{dust}} td {{hitCount}} td {{rating}} td {{commentCount}} tbody each getGuides tr td {{hero}} td a(href="/guide/{{formatId _id}}") {{title}} td {{authorUsername}} td {{moFormat modifiedAt 'YYYY-MM-DD'}} td {{dust}} td {{hitCount}} td {{rating}} td {{commentCount}} 

Any help or suggestions are welcome!

Edit: I upgraded the search-source package to 1.4.2

+6
source share
2 answers

I believe the problem is the lack of options passed to GuideSearch.search method.

This causes the search definition handler to get null for the parameters.

 SearchSource.defineSource('guides', function(searchText, options) { if(searchText) { var regExp = buildRegExp(searchText); var selector = {title: regExp} return Guides.find(selector, options).fetch(); //illegal } else { return Guides.find({}, options).fetch(); } }); 

This causes the find() collection method to get null arguments, which, if specified, should be an object (not null ).

Therefore, either check for options zero in the data source and pass an empty object (or nothing) to the find() method, or pass an empty object to the GuideSearch.search() method:

 Template.guide_list.events({ "keyup #title": _.throttle(function(e) { var text = $(e.target).val().trim(); GuideSearch.search(text, {}); // here }, 200) }); 

You should probably make sure that options are not null in the server method, as in @webdeb's answer anyway.

In addition, at the moment some packages ( check and ejson ) should be added as dependencies to your application, since the meteorhacks:search-source package uses them without declaring a dependency. This is due to changes made in v1.2.0. (before that, these symbols were automatically available for packages).

To get the original results, you can initiate a search when the template is first created. Note that this can be quite expensive when you have a lot of data, so you should probably limit the results returned by the search definition handler on the server.

 Template.guide_list.onCreated(function () { GuideSearch.search('', {}); }); 

To correctly display the title in the search results, you can use Spacebars.SafeString() to know how to do this, like HTML.

 Template.guide_list.helpers({ getGuides: function () { return GuideSearch.getData({ transform: function (matchText, regExp) { return Spacebars.SafeString(matchText.replace(regExp, "<b>$&</b>")) } }); }, formatId: function(id) { return id; }, moFormat: function(date, format) { return moment(date).format(format); }, isLoading: function () { return GuideSearch.getStatus().loading; } }); Template.guide_list.events({ "keyup #title": _.throttle(function(e) { var text = $(e.target).val().trim(); GuideSearch.search(text, {/* your options here */}); }, 200) }); 

or alternatively use triple-bracket notation:

 a(href="/guide/{{formatId _id}}") {{{title}}} 

Warning: be sure to clean matchText with this.

Publications should not have anything to do with the results, as the package uses its own collection.

+3
source

I agree with the answer from @MasterAM, but to solve this problem just put this in your SearchSource function:

  SearchSource.defineSource('guides', function(searchText, options) { options = options || {}; // to be sure, that options is at least an empty object if(searchText) { var regExp = buildRegExp(searchText); ... 
+1
source

All Articles