【发布时间】:2016-05-10 12:55:56
【问题描述】:
我有这个产品集合,我想根据自定义排序函数显示top 10 products
[{ _id: 1, title, tags:['a'], createdAt:ISODate("2016-01-28T00:00:00Z") } ,
{ _id: 2, title, tags:['d','a','e'], createdAt:ISODate("2016-01-24T00:00:00Z") }]
我想做的是根据可以计算的“魔术分数”对其进行排序。例如,根据这个公式:tag_count*5 - number_of_days_since_it_was_created。
如果第一个是 1 天大,则得分:
[{_id:1 , score: 4}, {_id:2, score: 10}]
我对如何实现这一点有一些想法,但我不确定它们有多好,特别是因为我对 mongo 和流星都是新手:
启动一个观察者 (Meteor.observe) 并且每次有一个文档 修改(或创建新的),重新计算分数并更新它 关于收藏本身。如果我这样做,我可以使用 $orderBy 我需要它。
阅读后我发现 mongo 聚合或 map_reduce 可以帮助我达到同样的效果,但据我所知, 流星不直接支持
将客户端的集合排序为数组,但使用这个 方法我不确定它会如何处理分页(考虑到我订阅的文档数量有限)
感谢您提供任何可以与我分享的信息!
【问题讨论】:
-
在运行时执行此操作的唯一方法是实现聚合语句,因为您无法提供以任何其他方式对服务器端进行排序的函数(请注意,除了键之外,mapReduce 不会对结果进行排序减少是排序的,但也不适合对计算字段进行分页)。考虑到您的要求,另一种方法是存储该字段并每天简单地重新计算(也可能在更新时)。这是一个简单的计划任务,然后是对现有字段的基本排序。这样也能提高性能。
-
因此,与其为每个产品更新添加事件侦听器,我更愿意偶尔运行一次 cron 吗?老实说,这确实有道理,尤其是因为我不需要实时得分。至于如何做到这一点,我应该使用
cursor.each()还是有更好的选择?我还没有弄清楚我是否可以在 mongodb 中做这样的事情:"UPDATE products SET score = tags_count * 10",我根据其他人的值设置了一个字段。谢谢@BlakesSeven -
就是这个想法。您的要求声明“几天前”,因此听起来不需要实时。预先计算的存储似乎绝对是要走的路。
-
或者您可以编写一个自定义发布函数,您可以在其中做几乎任何您想做的事情。您可以按照文档 docs.meteor.com/#/full/meteor_publish 中的“按房间计数”示例进行操作。
-
我也尝试过这种方法,但您几乎无法为所欲为。例如,我找不到可以将此方法与 $limit 一起使用的方法(因此我不发布所有文档)。我所能做的就是在客户端上发布一个“分数”以及所有添加的文档:function(id, fields) { fields.score = fields.tags.length* 15; self. added("产品", id, fields); }`