我正在使用Meteor.js进行过滤的实时搜索模块。
Usecase&问题:
用户想要搜索所有用户以查找朋友。但我无法让每个用户询问完整的用户集合。用户使用复选框过滤搜索。我想订阅匹配的用户。最好的方法是什么?
我想最好创建查询客户端,然后发送方法以获取所需的用户集。但是,我想知道:当过滤标准发生变化时,新订阅是否会删除所有旧订阅?因为,如果我执行的第一次搜索会返回[usr1, usr3, usr5]
,之后会返回给我[usr2, usr4]
的搜索,那么最好保留第一组,然后只需将新的一个添加到客户端嫌疑人收集。
另外,如果那时我做了第三次研究,应该返回我[usr1,usr3,usr2,usr4],自动调用的订阅不会发送任何内容,因为我已经在我的集合中拥有了整个结果集。 / p>
目标是从服务器中节省处理和数据传输。
我有一些想法,但我还没有足够的编码来以一种简单易懂的方式分享它。
在节省时间和性能方面,您如何建议我做更多相关的事情?
谢谢大家。
大卫
答案 0 :(得分:1)
这取决于您的应用程序,但您可能会向发布者发送非空字符串,该发布者使用该字符串在用户集合中搜索匹配的名称。例如:
Meteor.publish('usersByName', function(search) {
check(search, String);
// make sure the user is logged in and that search is sufficiently long
if (!(this.userId && search.length > 2))
return [];
// search by case insensitive regular expression
var selector = {username: new RegExp(search, 'i')};
// only publish the necessary fields
var options = {fields: {username: 1}};
return Meteor.users.find(selector, options);
});
另请参阅common mistakes了解我们限制字段的原因。
<强>性能强>
Meteor足够聪明,可以跟踪每个客户为每个发布者提供的当前文档集。当发布商重新运行时,它知道只在集合之间发送差异。所以你上面描述的情况已经为你解决了。
removed
消息和4消息。请注意,如果您在重新运行之前停止订阅,则不会发生这种情况。
据我所知,在修改单个订阅的参数时,没有办法避免removed
消息。我可以想到两种可能的(但很棘手的)替代方案:
累积所有先前搜索查询的交集,并在订阅时使用该查询。例如,如果用户搜索了{height: 5}
,然后搜索了{eyes: 'blue'}
,则可以使用{height: 5, eyes: 'blue'}
进行订阅。这可能很难在客户端上实现,但它应该以最小的网络流量完成您想要的任务。
累积有效订阅。每次用户修改搜索时,不是修改现有订阅,而是为新文档集启动新订阅,并将订阅句柄推送到数组。当模板被销毁时,您需要遍历所有句柄并在其上调用stop()
。这应该可行,但它会消耗更多资源(网络和服务器内存+ CPU)。
在尝试这些解决方案之前,我建议在不使用它们的情况下对最坏情况进行基准测试。我主要担心的是,如果没有相当严格的控制,您可能会在连续搜索后最终发布整个用户集合。
答案 1 :(得分:0)
如果您希望在服务器上轻松实现,则需要尽可能少地向客户端发送数据。这意味着您发送给不是朋友的客户的每个文档都是浪费。所以,让我们消除所有浪费。
收集过滤器(例如limit:20
)。然后调用一个方法来根据你的过滤器进行搜索(例如{{1}}。另外,你可以运行你自己的专有排名算法来确定一个人是朋友的百分比。也许是基于与ip地址的距离(或者从手机GPS历史记录),共同的朋友等。这将在效率方面带来好处。像GPS坐标或其他高度独特的属性这样的索引可能会尝试复合索引。但是记住更多的索引意味着更慢的写入。
现在你已经拥有了所有可能的朋友的光标,从最可能的最可能的排名。
接下来,更改您的订阅以匹配这些朋友,但在那里放置{{1}}。此外,只发送您需要的字段。这样,如果用户想跳过此步骤,您只会浪费通过网络发送20个部分文档。然后,有一个无限滚动或“加载更多”按钮,用户可以单击。当它们加载更多时,它是一个附加订阅,因此它不会重新发送重复信息。发现Meteor非常详细地描述了这种模式,所以我不会。
点击几下/滚动后,用户就找不到更多的朋友了(因为你很聪明并对它们进行了排序),所以他们会停止尝试&amp;继续下一步。如果你回来了200个可能的朋友&amp;他们在60后停止尝试,你刚刚通过管道保存了140个文档。这是你的效率。