2011-12-09 29 views
0

假设我有一组对象。我有另一个喜欢的集合,每个集合都由特定的用户和特定的对象组成。因此,随着时间的推移,通过用户评分,每个对象具有可变数量的喜欢(全部大于0)。一种基于评分从集合中选择选择的算法?

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

我现在要记住的算法是,按照喜欢的顺序排列对象,并生成一个随机数,并使用数字来选择一个范围内的随机对象。假设我有一百个对象,则选择0-10的时间对象的50%被选中,10-15的时间的25%和15-100的时间的25%。

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

回答

1

我会反正规化一点,并添加一个'喜欢'计数器字段到被喜欢的对象。对象获得喜欢时递增,当对象不被喜欢时递减。

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

然后我也有一个代表该对象是为喜欢的结果斗另一个领域。因此,例如,对象开始时这个字段设置为“普通”,并且在有人获得10个喜欢后,他们将成为“精英”。 (或任何你想要的)当它们达到该阈值时更新它。这里的想法是,在写入过程中进行工作会使读取操作更容易。

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

好吧,现在选择基于#of likes定义的组中的对象组很容易吧? 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} })

你觉得呢?

+0

什么是'算法'?算法过去了'街道'? –

+0

米奇请... –

+1

我接受了你的建议,并用类似的列进行了非规范化处理。现在,我只是要使用skip方法,但是如果我看到数据增加和缩放问题,那么随机生成结果的方法似乎很棒! – MEURSAULT