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

What's the most efficient way to apply a function to all objects in a collection in MongoDB?

本文关键字:对象 有效 方法 是什么 函数 应用于 集合 MongoDB      更新时间:2023-09-26

假设我想计算集合中所有对象的"popularity"字段。它取决于从当前时间到字段"submitTime"和字段"votes"中的数字的差值。这个手术每小时进行一次。在所有对象上运行函数的最有效方法是什么?只是一个例子,它可以是任何函数:

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

如果要在所有对象上运行一个函数并保存原始集合中的流行度评分,那么最好的方法是遍历所有文档以计算并保存新评分。如果你想保存到一个不同的集合,你可以使用MapReduce来代替。

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

提高效率

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

  • 将您的更新标准限制为拥有超过0票的文档(否则无论如何您将被除以零)
  • 只检索您需要计算流行度的字段,并使用$set更新流行度字段,而不是重新保存整个文档。
  • 当您添加个人投票时更新人气评分(避免每小时完整召回所有分数),然后做一个不太频繁的(例如。

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

  • 使用数字流行度度量,其中事件和用户操作(例如;文章发表,用户意见/投票/,…)会增加不同的人气值。随着时间的推移,受欢迎程度逐渐下降。Drupal的radiation模块通过基于规则的方法实现了这一点。

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

  • 添加一个整数popularity字段,其中新对象从某个值(例如1000)开始
  • 有不同的用户操作(新的投票,意见等)增加人气计数器使用$inc适当的数量(例如50为一个新的投票)
  • 使用定期调度的作业来减少受欢迎程度。
  • 由于所有流行度都以正分数开始并衰减到0或更小,因此您可以将更新查询限制为流行度>0的文档。
  • 您还可以(ab)使用流行度评分来确保重要文档的流行时间更长。

关于"什么是好的流行度度量"有更多的细微差别,并且在StackOverflow上有很多以前的问题(例如:应该使用什么公式来确定"热门"问题?)。