使用Google App Engine排序问题

时间:2010-01-02 08:54:09

标签: python google-app-engine google-cloud-datastore

我使用以下类来存储一些数据:

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实体,然后在我的应用程序中进行分数排序,但我期待大量的结果,因此内存排序效率不高。

我的问题可能还有哪些其他解决方案?

4 个答案:

答案 0 :(得分:5)

你可以:

  1. 仅按时间范围过滤,并按内存中的分数排序,或

  2. 如果您可以将时间范围限制为整天和几周,请在模型中包含其他属性,以将整周保存为整数,将日期保存为DateProperty并对其执行简单的相等检查

  3. 编辑:要了解更多信息,请查看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)