当前位置:  开发笔记 > 编程语言 > 正文

如何在数据存储区(AppEngine)中随机获取内容?

如何解决《如何在数据存储区(AppEngine)中随机获取内容?》经验,为你挑选了3个好方法。

目前我正在使用这样的东西:

    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.

有没有更好的方法来检索随机图像?



1> Drew Sears..:

数据存储是分布式的,因此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的建议更新了坠落案例.


此解决方案仅适用于具有许多实体且存在大量流失的数据存储.如果只有少数实体不经常改变,那么一些实体的选择往往远远超过其他实体.在极端情况下,如果数据存储区中只有两个实体分别具有rand_num .01和.99,则几乎每次都会选择第一个实体.为了解决这个问题,(1)定期更改rand_num(可能在每个查询中)和(2)随机使用"> ="和"<"运算符.
在`entity is None`的情况下,你应该简单地获取第一个实体,由`rand_num`排序,从而将实体视为循环缓冲区.你目前的做法使得最后一个实体比其他实体更有可能被选中.

2> Will Curran..:

另一种解决方案(如果您不想添加其他属性).将一组密钥保存在内存中.

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个实体的查询更有效).



3> 小智..:

我认为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()都会对性能产生影响.

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有