我使用以下类来存储一些数据:
class NewsArticle(db.Model):
score = db.FloatProperty(default=0.0)
date_scored = db.DateTimeProperty()
...
我需要做的是让那些在某个时间段内获得最高分的NewsArticle实体(例如获得今天或上周得分最高的数据实体)。
我尝试了以下内容:
query = db.GqlQuery('SELECT * FROM NewsArticle WHERE date_created > DATETIME(:year, :month, :day, 0, 0, 0) ORDER BY score DESC', year=date.selected_year, month=date.selected_month, day=date.selected_day)
但是这不起作用,因为数据存储需要
首先订购物业必须是 与不等式过滤属性相同
我考虑过在特定的时间范围内获取所有NewsArticle实体,然后在我的应用程序中进行分数排序,但我期待大量的结果,因此内存排序效率不高。
我的问题可能还有哪些其他解决方案?
答案 0 :(得分:5)
你可以:
仅按时间范围过滤,并按内存中的分数排序,或
如果您可以将时间范围限制为整天和几周,请在模型中包含其他属性,以将整周保存为整数,将日期保存为DateProperty
并对其执行简单的相等检查
编辑:要了解更多信息,请查看Restrictions on Queries
答案 1 :(得分:1)
我期待一个非常大的数字 结果所以内存排序不会 高效。
您可以从查询中获得最多1000个结果,因此按照非常高效对其进行排序 - 例如,考虑一下,在我的Macbook Air上(第一天,最慢的模型):
$ python -mtimeit -s'import random; x=range(1000); random.shuffle(x)' 'y=sorted(x)'
1000 loops, best of 3: 714 usec per loop
AppEngine的CPU比Air快得多,因此对1000个结果进行排序的700微秒将是非常悲观估计;这与提取数据的数十毫秒相比 - 所以,不要担心完全关于排序:只要您可以获取你想要的结果,你会没事的。
BTW,为了评估App Engine在任务上的表现,请参阅Guido van Rossum的演讲here - 他声称“典型db.get()
”为10-50毫秒({{50}为{{ 1}}等。)
如果您希望查询的结果超过1000,这通常意味着您需要对表进行非规范化,以将查询的结果修剪为1000以下。例如,在您的情况下,假设您预计每天会有大约500-700个条目 - 在这种情况下获取今天的所有结果都没有问题,但一周 肯定是一个问题:你需要将查询减少到“通常”的20%或更少
例如,假设您的分数在0-100范围内,大致均匀分布。在这种情况下,您可以向实体添加一个布尔字段“topcandidate”:当您保存实体时,如果分数在85-100范围内,则将该字段设置为True(如您所见,这意味着表格被非规范化,因为该字段代表逻辑冗余信息)。
当您获取每周最高结果时,添加相等条件以使topcandidate为True。而不是3500-4900的结果,这应该让你降到500-900 - 得分最高的15%左右,之后你可以在内存中排序并选择前100名。
当然,确切的数字取决于put
字段的分布(更可能是钟形曲线而不是平坦的均匀分布)以及您需要多少“最佳候选人”,但这通常是一个有效的方法来解决1000个结果限制。
答案 2 :(得分:0)
试试这个:
import datetime
...
query = Data.gql('SELECT * FROM NewsArticle WHERE date_created >= :today ORDER BY score DESC', today=datetime.date.today())
答案 3 :(得分:-1)
我认为通过多个属性进行排序可能会有效。只需使用第一个不等式属性作为第一个排序属性。
query = db.GqlQuery('SELECT * FROM NewsArticle WHERE date_created > DATETIME(:year, :month, :day, 0, 0, 0) ORDER BY date_created, score DESC', year=date.selected_year, month=date.selected_month, day=date.selected_day)