目前我正在使用这样的东西:
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。
有没有更好的方法来检索随机图像?
答案 0 :(得分:18)
数据存储是分布式的,因此ID是非顺序的:两个数据存储节点需要能够同时生成ID而不会引起冲突。
要获取随机实体,您可以在创建时为每个实体附加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()
编辑:根据尼克的建议更新了堕落案例。
答案 1 :(得分: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)
上面的代码说明了仅获取密钥然后创建随机集的基本方法,用于执行批量获取。您可以将该组密钥保存在内存中,在创建新的ItemUser实体时添加该密钥,然后使用返回 n 随机实体的方法。您将不得不实施一些管理memcached密钥的开销。如果你经常对随机元素执行查询,我更喜欢这个解决方案(我假设使用批量获取 n 实体比 n 实体的查询更有效) 。
答案 2 :(得分: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]
不需要其他属性,但缺点是如果Images的数量很大,count()和fetch()都会对性能产生影响。
答案 3 :(得分:1)
另一种(效率较低)方法,无需设置:
query = MyModel.all(keys_only=True)
# query.filter("...")
selected_key = None
n = 0
for key in query:
if random.randint(0,n)==0:
selected_key = key
n += 1
# just in case the query is empty
if selected_key is None:
entry = None
else:
entry = MyModel.get(selected_key)