将函数应用于MongoDB中集合中所有对象的最有效方法是什么?

时间:2013-04-06 22:26:35

标签: javascript node.js mongodb

假设我想计算集合中所有对象的“受欢迎程度”字段。它取决于当前时间与“submitTime”字段的差异以及“投票”字段中的数字。此操作将每小时运行一次。在所有对象上运行函数的最有效方法是什么?举个例子,它可以是任何功能:

function(){
    this.popularity = this.votes / (Date.now() - this.submitTime);
}

1 个答案:

答案 0 :(得分:1)

如果要在所有对象上运行函数并在原始集合中保存流行度分数,则最佳方法是迭代所有文档以计算并保存新分数。如果您想保存到其他收藏品,可以使用MapReduce代替。

如果您对如何计算受欢迎程度的其他想法持开放态度,可以选择更多选项:)。

提高效率

为了提高当前方法的效率,您可以:

  • 将更新条件限制为投票数超过0的文档(否则您将被除以零)
  • 仅检索计算受欢迎程度所需的字段,并使用$set更新受欢迎程度字段,而不是重新保存完整文档。
  • 添加个人投票时更新人气分数(避免每小时完全重新计算所有分数),然后不太频繁(例如每晚)重新计算所有投票

替代方法

  • 使用可通过排序而非计算确定的流行度量标准。例如:{ votes: -1, lastVotedTime: -1, submitTime: -1 }。但是,这可能无法满足您对旧文档流行度老化的要求。

  • 使用数字流行度指标,其中事件和用户操作(例如,文章发布,用户观看/投票/,......)将添加不同的流行度值。随着时间的推移,人气衰退。 Radioactivity module for Drupal使用基于规则的方法实现此目的。

要在MongoDB中实现后一种方法,您可以:

  • 添加整数popularity字段,其中新对象以特定值(例如1000)开始
  • 让不同的用户操作(新投票,观看等)使用$inc以适当的金额(例如50为新投票)增加受欢迎度计数器
  • 使用定期安排的工作随着时间的推移减少人气。
  • 由于所有受欢迎程度均以正分开始并且衰减为0或更低,因此您可以将更新查询限制为> 0受欢迎程度的文档。
  • 您还可以(ab)使用受欢迎程度得分来确保重要文档的使用时间更长。

“什么是良好的人气指标”还有更多细微差别,以及关于StackOverflow的大量先前问题(例如:What formula should be used to determine “hot” questions?)。