我有一个流星应用程序,我想让用户点击按钮在两个不同的数据过滤视图之间切换,比如" chart"状态为10或11的记录。应用程序的某些用户可能永远不希望看到状态10,而其他用户可能永远不希望看到状态11。
我试图找到一种通过发布/订阅的方式来最有效地解决这个问题...不要提取某些人不想看到的记录,同时还要减少网络流量。
第一个想法是以下...在服务器上发布状态参数:
Meteor.publish("charts1", function (status) {
console.log('someone subscribed to my publish of charts.. returning all charts now of status ' + status + " max 500 though");
return Chart.find({"chartStatus": status}, {limit: 500, sort: {"demographics.lastName": 1}});
});
然后,在客户端上,我有一个模板助手:
chartsOnClient: function () {
return Chart.find({"chartStatus":Session.get('currentStatusFilter')}, {sort: {"demographics.lastName": 1}});
}
和2个按钮,单击时将设置会话过滤器并同时订阅:
Template.addChartForm.events = {
'click #mybutton10': function () {
console.log("subscribing to to status 10...");
Session.set('currentStatusFilter', 10);
Meteor.subscribe('charts1', 10);
},
'click #mybutton11': function () {
console.log("subscribing to status 11...");
Session.set('currentStatusFilter', 11);
Meteor.subscribe('charts1', 11);
},
}
,当然,还有一个模板,它遍历" chartsOnClient"显示记录。
这很有效...当我点击button10时,我的模板中获得了状态10,然后点击button11在我的模板中给了我状态11 ...而且,额外的好处是,如果我从未点击过button11,我的本地客户端只保存状态10的记录,反之亦然,单击这两个按钮将填充我的本地集合与两个集合的联合。
我看到这个方法的唯一问题是,每次点击按钮都会产生服务器消息"有人订阅了我发布的图表......" ...表示客户端正在谈话到服务器并运行find方法。
我怀疑这不太理想...因为,如果我想,我可以移动2"订阅"在点击事件中调用外部,如下所示:
Meteor.subscribe('charts1', 10);
Meteor.subscribe('charts1', 11);
Template.addChartForm.events = {
'click #mybutton10': function () {
console.log("subscribing to to status 10...");
Session.set('currentStatusFilter', 10);
},
'click #mybutton11': function () {
console.log("subscribing to status 11...");
Session.set('currentStatusFilter', 11);
},
}
当我这样做时,我获得了相同的最终用户体验,但是,服务器控制台仅在启动时显示"有人订阅了我的发布" ...消息,而不是每次都单击按钮。
缺点是两组记录都会被拉到每个用户的客户端,甚至是那些可能永远不会点击这两个按钮的用户。但好处是每次点击切换数据视图时都不会调用subscribe方法......
我有什么不明白的吗?哪种方法最好?是否有更好的方法来完成这项工作?我是meteor和mongo的新手。
谢谢。
编辑,基于@mattk,我将在按钮点击中进行订阅,但如果我已经订阅了该特定过滤器,则在会话变量中使用数组以防止第二次订阅:
'click #mybutton10': function () {
Session.set('currentStatusFilter', 10);
var filtersAppliedSoFar = Session.get('filtersAppliedSoFar');
if (filtersAppliedSoFar.indexOf(10) == -1) {
console.log("subscribing to to status 10...");
filtersAppliedSoFar.push(10);
Session.set('filtersAppliedSoFar', filtersAppliedSoFar);
Meteor.subscribe('charts1', 10);
}
},
'click #mybutton11': function () {
Session.set('currentStatusFilter', 11);
var filtersAppliedSoFar = Session.get('filtersAppliedSoFar');
if (filtersAppliedSoFar.indexOf(11) == -1) {
console.log("subscribing to status 11...");
filtersAppliedSoFar.push(11);
Session.set('filtersAppliedSoFar', filtersAppliedSoFar);
Meteor.subscribe('charts1', 11);
}
},
这样,我不会在用户点击特定过滤器之前提取数据,但如果他们在2个过滤器之间来回点击,我也不会重新订阅,这是预期的。< / p>
再次编辑:在询问此问题How do you securely log out and clear all subscriptions?并转向订阅管理器https://github.com/meteorhacks/subs-manager后,我发现订阅管理器实现了我在这里寻找的内容:我不希望它发生如果我的客户再次调用.subscribe,则第二次服务器。不使用会话变量(filtersAppliedSoFar)来了解客户端是否已经订阅,子管理器会自动跟踪这个...我只是在订阅管理器对象上调用.subscribe,它不会命中服务器第二次。 ..然后额外的好处是我可以在注销时调用.clear()并停止所有订阅。
答案 0 :(得分:4)
你的第一个模式没有任何问题。每当你与服务器交谈时,你想要它或者告诉它一些新东西,这正是你正在做的事情:你只需要它来获取你需要的数据。如果要减少带宽,请限制返回的fields
;您可能不需要存储在文档中的每个字段。
我遵循这样的事情:
//Client code (event click)
Meteor.subscribe('patients',
{"chartStatus":Session.get('currentStatusFilter')},
{
fields: {'demographics': 1, 'chartStatus': 1},
sort: {"demographics.lastName": 1}
});
//Server code
Meteor.publish('patients', function(query, options) {
if (options) {
check(options, {
sort: Match.Optional(Object),
limit: Match.Optional(Number),
fields: Match.Optional(Object)
});
}
return Patients.find(query,options);
});
请注意,客户现在可以询问她想要的任何字段。如果将来文档中的某些字段不应通过网络发送,您也需要进行权限检查。现在,这对你来说似乎不是一个问题,因为你已经发送了整个文档。