【问题标题】:custom sort for a mongodb collection in meteor流星中mongodb集合的自定义排序
【发布时间】: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 和流星都是新手:

  1. 启动一个观察者 (Meteor.observe) 并且每次有一个文档 修改(或创建新的),重新计算分数并更新它 关于收藏本身。如果我这样做,我可以使用 $orderBy 我需要它。

  2. 阅读后我发现 mongo 聚合或 map_reduce 可以帮助我达到同样的效果,但据我所知, 流星不直接支持

  3. 将客户端的集合排序为数组,但使用这个 方法我不确定它会如何处理分页(考虑到我订阅的文档数量有限)

感谢您提供任何可以与我分享的信息!

【问题讨论】:

  • 在运行时执行此操作的唯一方法是实现聚合语句,因为您无法提供以任何其他方式对服务器端进行排序的函数(请注意,除了键之外,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); }`

标签: mongodb sorting meteor


【解决方案1】:

文字函数排序is just being implemented in meteor,所以你应该可以做类似的事情

Products.find({}, {sort: scoreComparator});

在即将发布的版本中

您可以使用transform property when creating collection。在此转换中,将魔术操作存储为函数。

score=function(){
    // return some score
};
transformer=function(product){
  product.score=score; 
  // one could also use prototypal inheritance 
};
Products=new Meteor.Collection('products',{transform:transformer});

很遗憾,you cannot yet use the sort operator on virtual fields,因为 minimongo 不支持它。

因此,正如您提到的,在 minimongo 中既不支持虚拟字段排序也不支持文字函数排序的最终后备是客户端排序:

// Later, within some template 
scoreComparator=function(prd1,prd2){
  return prd1.score()-prd2.score(); 
}
Template.myTemplate.helpers({
  products:function(){
    return Products.find().fetch().sort(scoreComparator);
  }
});

我不确定分页会如何表现(考虑到我订阅的文档数量有限)

EDIT :确实会在订阅的文档中计算分数。

【讨论】:

    猜你喜欢
    • 2018-01-25
    • 2015-01-19
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    • 2015-02-23
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    相关资源
    最近更新 更多