如何使用Objectify从 Google App Engine 数据存储中获取随机元素?我应该获取所有实体的密钥并从中随机选择还是有更好的方法?
4 回答
存储时为每个实体分配一个 0 到 1 之间的随机数。要获取随机记录,请生成另一个介于 0 和 1 之间的随机数,并查询具有大于该随机值的最小实体。
从这篇文章中引用了关于从 Objectified 数据存储中选择一些随机元素的内容:
如果您的 id 是连续的,一种方法是从已知正在使用的 id 范围中随机选择 5 个数字。然后使用带有“in”filter() 的查询。
如果您不介意 5 个条目相邻,则可以使用 count()、limit() 和 offset() 来随机查找包含 5 个条目的块。
否则,您可能需要使用 limit() 和 offset() 一次随机选择一个条目。
——乔什
您不需要全部获取。例如:
- countall = query(X.class).count() // http://groups.google.com/group/objectify-appengine/browse_frm/thread/3678cf34bb15d34d/82298e615691d6c5?lnk=gst&q=count#82298e615691d6c5
- rnd = 生成随机数 [0..countall]
- ofy.query(X.class).order("-date").limit(rnd); //例如 -date 或一些长期索引字段
- 最后一个 id 是你的……(平均而言,你获得 50% 或至少第一次阅读平均少 50%)
改进(在缓存中有更小的键表)!
在第一次阅读后记住每个 X 元素。缓存 id-s 及其位置。因此,下次从所选 id 进一步查询条件(最大“.limit(rnd%X)”将为 X-1)。
随机只是随机,如果不需要接近 100% 公平,则推测慢性字段值(例如,如果您在 10 天内有 1000 条记录,对于随机 501 选择大于第五天的第二个元素)。
其他选项,如果您有长期字段日期(或类似日期),则获取早于随机日期和更早于随机日期 + 1 的元素(您需要知道第一个日期和最后一个日期)。第二次在获取的记录之间随机选择。如果查询为空,则选择大于等...
我非常适应 Matejc 提供的算法。但是,有 3 件事:
我没有使用 count() 或数据存储服务工厂 (DatastoreServiceFactory.getDatastoreService()),而是有一个实体来跟踪我感兴趣的实体的总数。这种方法的原因是:当您处理大量对象时,count() 可能会很昂贵 b. 您无法在本地测试数据存储服务工厂...在 prod 中进行测试只是一种不好的做法。
生成随机数:ThreadLocalRandom.current().nextLong(1, maxRange)
我没有使用limit(),而是使用offset,所以我不必担心“排序”。