目前我正在使用这样的东西:
images = Image.all() count = images.count() random_numb = random.randrange(1, count) image = Image.get_by_id(random_numb)
但事实证明AppEngine数据存储区中的ID不是从1开始的.我在数据存储区中有两个图像,它们的ID是6001和7001.
有没有更好的方法来检索随机图像?
数据存储是分布式的,因此ID是非顺序的:两个数据存储节点需要能够同时生成ID而不会导致冲突.
要获取随机实体,可以在create上为每个实体附加0到1之间的随机浮点数.然后查询,做这样的事情:
rand_num = random.random() entity = MyModel.all().order('rand_num').filter('rand_num >=', rand_num).get() if entity is None: entity = MyModel.all().order('rand_num').get()
编辑:根据Nick的建议更新了坠落案例.
另一种解决方案(如果您不想添加其他属性).将一组密钥保存在内存中.
import random # Get all the keys, not the Entities q = ItemUser.all(keys_only=True).filter('is_active =', True) item_keys = q.fetch(2000) # Get a random set of those keys, in this case 20 random_keys = random.sample(item_keys, 20) # Get those 20 Entities items = db.get(random_keys)
上面的代码说明了获取密钥然后创建随机集的基本方法,用于批量获取.您可以将该组密钥保存在内存中,在创建新的ItemUser实体时添加它,然后使用一个返回n个随机实体的方法.您将不得不实施一些管理memcached密钥的开销.如果你经常对随机元素执行查询,我更喜欢这个解决方案(我假设使用批量获取n个实体比n个实体的查询更有效).
我认为Drew Sears上面的回答(在创建时为每个实体附加一个随机浮动)有一个潜在的问题:每个项目都没有相同的机会被选中.例如,如果只有2个实体,并且一个获得0.2499的rand_num,另一个获得0.25,那么0.25将逐渐被选中.这可能对您的应用程序有效,也可能无关紧要 您可以通过在每次选择时更改实体的rand_num来解决此问题,但这意味着每次读取也需要写入.
pix的答案将始终选择第一个键.
这是我能想到的最好的通用解决方案:
num_images = Image.all().count() offset = random.randrange(0, num_images) image = Image.all().fetch(1, offset)[0]
不需要其他属性,但缺点是如果Images的数量很大,count()和fetch()都会对性能产生影响.