use*_*171 17 python google-app-engine
目前我正在使用这样的东西:
images = Image.all()
count = images.count()
random_numb = random.randrange(1, count)
image = Image.get_by_id(random_numb)
Run Code Online (Sandbox Code Playgroud)
但事实证明AppEngine数据存储区中的ID不是从1开始的.我在数据存储区中有两个图像,它们的ID是6001和7001.
有没有更好的方法来检索随机图像?
Dre*_*ars 18
数据存储是分布式的,因此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()
Run Code Online (Sandbox Code Playgroud)
编辑:根据Nick的建议更新了坠落案例.
Wil*_*ran 10
另一种解决方案(如果您不想添加其他属性).将一组密钥保存在内存中.
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)
Run Code Online (Sandbox Code Playgroud)
上面的代码说明了获取密钥然后创建随机集的基本方法,用于批量获取.您可以将该组密钥保存在内存中,在创建新的ItemUser实体时添加它,然后使用一个返回n个随机实体的方法.您将不得不实施一些管理memcached密钥的开销.如果你经常对随机元素执行查询,我更喜欢这个解决方案(我假设使用批量获取n个实体比n个实体的查询更有效).
小智 6
我认为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]
Run Code Online (Sandbox Code Playgroud)
不需要其他属性,但缺点是如果Images的数量很大,count()和fetch()都会对性能产生影响.