MongoDB:按相关性功能排序

时间:2015-03-03 14:19:22

标签: mongodb meteor nosql

我想创建一个基本的排序算法,该算法由mongodb和meteor中的相关性决定。但是,我无法静态存储并更新它,因为它使用当前时间作为参数之一。

理想情况下,我想拥有的内容如下:

Post.relevance = function(magnitude) {
  magnitude = magnitude || 1.8;
  check(magnitude, Number);
  var score = this.upvotes - this.downvotes;
  var hoursAgo = moment().hours - moment(this.createdAt).hours();
  return (score - 1) / Math.pow((hoursAgo + 2), magnitude);
}

从我收集的内容中,我将不得不使用aggregation pipeline来生成此查询,但我无法获得帖子页面的详细信息。

如何使用mongodb生成此高级查询?

1 个答案:

答案 0 :(得分:3)

算法取决于您如何定义相关性。

在继续之前,我想提一下,我之前没有在生产环境中实现过这样的算法,我只是就如何解决这个问题表达了我的个人意见。

就个人而言,根据您的架构,我会考虑以下方法在确定相关性时最常见:

  • 在受欢迎程度方面的相关性 - 这就是搜索引擎的方式 确定内容的相关性:一个网站的观点越多, 更相关的是
  • 质量方面的相关性 - 在您的情况下,您可以根据upvotes / downvotes ratio找到动态生成的算法
  • 时间相关性 - 您当前使用时间作为过滤机制的算法量化相关性的方式;不过,我不会选择这个,因为相关内容永远是有价值的

在前面提到的3个场景中,我建议你在前两个场景中进行混音。

你必须找到一种很好的方式来表示视图流行度,upvotes和downvotes之间的关系。这意味着您首先必须更新数据库模式,以便为每个帖子保存一个视图计数:

{
    _id: ObjectId(...),
    title: 'A Random Post',
    authorId: ObjectId(...),
    createdAt: '01-01-1900',
    editedAt: '02-01-1900',
    upvotes: 76,
    downvotes: 15,
    viewCount: 8655,
    relevance:

}

之后,您可以确定计算相关性的公式。例如,如果您假设帖子获得的观看次数越多,它就越流行,您可以使用以下公式:

Relevance = viewCount * upvotes/downvotes

但是,最重要的部分是如何选择存储相关性属性。

在我看来,你有两种可能的选择:

  • 将其与所有其他元素一起存储在数据库中 - 这个 意味着您必须不断更新每个相关性 发布,同时不断为viewCount发布$inc更新, upvotes and downvotes
  • 在查询仅限数据库的问题后确定相关性 {c},upvotes和downvotes的$inc更新;拉后 来自数据库的数据,你将不得不解析结果 数组并量化相关性,而不将其存储在数据库中

显然,由于更多的更新操作,第一种情况会在服务器上产生更大的压力。不过,它允许您通过触发简单查询来查询相关帖子。

//Top 10 most relevant posts
db.posts.find({}).sort({ relevance: -1 }).limit(10);

如果你选择第二个选项,首先必须从数据库中提取所有文档,然后在从服务器发送数据之前做一些额外的工作来确定相关性。