0

假设我有一个对象集合。我还有另一组喜欢,每一个都来自一个特定的用户和一个特定的对象。因此,随着时间的推移,通过用户评分,每个对象都有可变数量的喜欢(都大于 0)。

我想从这个集合中选择一个对象。喜欢的对象应该更频繁地选择,但有时也应该选择喜欢的对象,给他们一个机会。

我现在想到的算法是按喜欢对对象进行排序,并生成一个随机数,并使用该数字在一个范围内选择一个随机对象。假设我有一百个对象,50% 的时间对象从 0-10 被选择,25% 的时间是 10-15,25% 的时间是 15-100。

该算法的明显问题是可扩展性。当他们有 1000000 个对象时,返回所有这些对象的数组需要时间。有没有人有更好的解决方案?数据库在 mongodb 中实现。

4

1 回答 1

1

我会去规范化一点,并为被喜欢的对象添加一个“喜欢”计数器字段。当对象被喜欢时增加它,当对象不喜欢时减少它。

db.test.insert({
    stuff: "likable stuff",
    likes: 7
})

然后我还会有另一个字段来表示对象所在的存储桶,因为喜欢。因此,例如,对象开始时将此字段设置为“普通”,在某人获得 10 个赞后,他们将成为“精英”。(或任何你想要的)当他们达到那个阈值时更新它。这里的想法是,在写入方面进行工作将使读取变得更加容易。

db.test.insert({
    stuff: "likable stuff",
    likes: 7,
    status: "ordinary/elite",
})

好的,现在选择您根据点赞数定义的组中的对象集很容易,对吧? db.collection.find({ status: 'elite' })

要在这些集合中随机选择文档,您可以随机跳过给定数量的记录,但这会导致糟糕的性能并且无法扩展。

但是,您可以使用一个技巧,将随机生成的数字存储在文档本身中。

让我们将其中一个人插入测试数据库并检查一下

db.test.insert({
    stuff: "likable stuff",
    likes: 7,
    status: "ordinary/elite",
    random: Math.random()
})

现在让我们看一下文档:

{
    stuff: "likable stuff",
    likes: 7,
    status: "ordinary/elite",
    random: 0.9375813045563468
}

好的,这就是它变得非常酷的地方。执行 findOne() 查询,其中状态:精英rand_num:$gt { 另一个随机生成的数字 btw 0 和 1 }。

db.collection.find({ status: "elite", random: { "$gt": new_rand_num } })

如果 findOne() 查询未返回结果,请使用 $lt 再次执行此操作,因为您将确保至少在其中一个方向上找到文档。

现在让我们索引状态和随机。

db.collection.ensureIndex({ status: 1, random: 1} })

你怎么看?

于 2011-12-09T02:05:31.753 回答