我在this上关注meteor search-source教程并修改了示例,以便符合我当前的需求。
这是我的collections.js
,它位于我的lib目录
Guides = new Mongo.Collection("guides");
我的客户端控制器中有以下代码。
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)
});
这是我的服务器端代码
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");
}
出于某种原因,我在输入字段中输入内容时收到以下错误消息
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
这是我的模板代码:
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}}
非常感谢任何帮助或建议!
修改:我将search-source
包更新为1.4.2
答案 0 :(得分:3)
我认为问题是options
方法缺少GuideSearch.search
。
这会导致搜索定义处理程序获得选项的null
。
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();
}
});
这导致集合的find()
方法获得空options
参数,如果提供,则必须是对象(而不是null
)。
因此,要么检查数据源中的空options
并将空对象(或什么都没有)传递给find()
方法,要么将空对象传递给GuideSearch.search()
方法:
Template.guide_list.events({
"keyup #title": _.throttle(function(e) {
var text = $(e.target).val().trim();
GuideSearch.search(text, {}); // here
}, 200)
});
在任何情况下,您应该确保服务器方法中的options
不是null
,而不是@ webdeb的答案。
此外,目前一些软件包(check
和ejson
)必须作为依赖项添加到您的应用程序,因为meteorhacks:search-source
软件包使用它们而不声明依赖项。这是由于v1.2.0中引入的更改。 (在此之前,这些符号自动可用于包)。
为了让所有结果最初可用,您可以在首次创建模板时触发搜索。 请注意,当您拥有大量数据时,这可能相当昂贵,因此您应该限制从服务器上的搜索定义处理程序返回的结果。
Template.guide_list.onCreated(function () {
GuideSearch.search('', {});
});
为了在搜索结果中正确显示标题,您可以使用Spacebars.SafeString()
,以便blaze知道将其呈现为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)
});
或者,使用三重括号表示法:
a(href="/guide/{{formatId _id}}") {{{title}}}
警告:请务必在执行此操作时清理matchText
。
出版物应该与结果无关,因为包使用自己的集合。
答案 1 :(得分:1)
我同意@MasterAM的答案,但要解决这个问题,请将其放入SearchSource
函数中:
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);
...