从Google App Engine数据存储中获取随机记录?

问题描述:

我有一个模型中有大约1,000,000个实体的数据存储。我想从中获取10个随机实体。从Google App Engine数据存储中获取随机记录?

我不知道该怎么做?有人可以帮忙吗?

+0

[在Appengine数据存储上查询N个随机记录]的可能重复(http://*.com/questions/1105004/querying-for-n-random-records-on-appengine-datastore) – 2011-08-31 19:32:07

为每个实体分配一个随机数并将其存储在实体中。然后查询随机数大于(或小于)某个其他随机数的十条记录。

然而,这并不是完全随机的,因为具有附近随机数的实体往往会一起出现。如果你想打败这个,做十个基于10个随机数的查询,但效率会比较低。

+0

没错。可能要提及随机数的范围(0..1是标准的)。 – 2010-06-09 09:16:17

+4

增加随机性而不损害读取时间效率的一种可能性是将任务分配给您获取的实体的新随机数,因此如果再次点击其中的一个,您将不会获得与它相同的邻居。 – geoffspear 2010-06-09 11:35:00

+0

@NickJohnson你能否澄清标准范围?对不起,我不明白你的意思(0..1)?另外,对于你们都:我很担心使用我的一个不平等过滤器进行此操作(因为在某些查询中,我需要它是随机的,但同时在另一个属性上运行相等过滤器)。做10次查询有多糟糕,基本上是成本的10倍? – iceanfire 2013-11-01 00:04:48

杰森霍尔的回答和the one here并不可怕,但正如他所提到的,他们也不是真的随机。例如,即使做十个查询也不会是随机的,例如,随机数都是组合在一起的。为了保持真正随机的,这里有两个可能的解决方案:

解决方案1 ​​

指定索引每个数据存储的对象,跟踪最大指数,并随机选择一个索引你想每次随机记录:

MyObject.objects.filter('index =', random.randrange(0, maxindex+1))

上行:真正的随机。快速。

下端:添加和删除对象时,必须正确地维护索引,这可以使两个操作都成为O(N)操作。

溶液2

分配一个随机数到每个数据存储数在创建时。然后,为了第一次获得一个随机记录,查询一个随机数大于某个其他随机数的记录,并用随机数排序(即MyObject.order('rand_num').filter('rand_num >=', random.random()))。然后将该查询作为游标保存在memcache中。要在第一次之后获得随机记录,请从memcache加载光标并转到下一个项目。如果第一个之后没有项目,请再次运行查询。

要防止重复对象序列,请在读取每个数据存储区时给刚刚读取的实体一个新的随机数并将其保存回数据存储区。

正面:确实是随机的。没有复杂的指标要维护。

低端:需要跟踪游标。每次你得到一个随机记录需要做一个放。

+0

“例如,如果随机数字全部组合在一起,即使执行十个查询也不会是随机的” - 我假定您正在讨论分配给数据存储行的随机数。对于少量记录来说,这只是一个问题 - 价值之间差距的标准差随着价值数量的增加而缩小,直至其在统计上不显着。您的解决方案1需要一个单调的计数器,这对App Engine来说是一个缓慢而昂贵的操作。解决方案2使用无需替换的选择,这与OP要求的不同。 – 2012-07-11 00:46:36

+0

对,如果没有很多记录或者如果您以高速率检索它们,天真的方法就会失败。另外,一旦rand_num值被设置,它们的分布就是固定的。你不会得到一个很好的统一分配,并且会有一些很少被选中的记录。 – speedplane 2012-07-11 03:36:51

+0

不,这是我的观点 - 您拥有的记录数量越多,间隔的标准偏差越小。也就是说,分配给它们的异常小间隔的实体将会成比例地减少。 Wooble在选择记录后重新分配号码的建议也有助于抵消这一点。 – 2012-07-11 04:10:44