是否可以在内存中重新排序查询结果?

时间:2014-05-08 22:24:21

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

并提前感谢任何和所有帮助!!

我在数据存储区上运行查询,如下所示:

forks = Thing.query(ancestor=user.subscriber_key).filter(
    Thing.status==True,
    Thing.fork_of==thing_key,
    Thing.start_date <= user.day_threshold(),
    Thing.level.IN([1,2,3,4,5])).order(
    Thing.level)

此查询有效并返回我期望的结果。但是,我想在一个额外的字段(Thing.last_touched)上对它进行排序。如果我将其添加到排序中,它将无法工作,因为Thing.last_touched不是应用不等式过滤器的属性。我无法添加额外的不等式过滤器,因为我们只允许使用一个,而且不需要它(实际上,这就是为什么Thing.leve.IN在那里......不需要作为过滤器,但需要排序)。

所以,我想知道的是,我可以使用我想要的过滤器运行查询,然后运行代码来自己对查询结果进行排序吗?我知道我可以拉出我想要排序的所有参数并将它们存储在字典中并按照这种方式对它们进行排序,但在我看来应该有办法用查询来处理它。

我已经搜索了好几天,但没有运气。

万一你需要它,这里是Thing的类定义:

class Thing(ndb.Model):
    title = ndb.StringProperty()
    level = ndb.IntegerProperty()
    fork = ndb.BooleanProperty()
    recursion_level = ndb.IntegerProperty()
    fork_of = ndb.KeyProperty()
    creation_date = ndb.DateTimeProperty(auto_now_add=True)
    last_touched = ndb.DateTimeProperty(auto_now=True)
    status = ndb.BooleanProperty()
    description = ndb.StringProperty()
    owner_id = ndb.StringProperty()
    frequency = ndb.IntegerProperty()
    start_date = ndb.DateTimeProperty(auto_now_add=True)
    due_date = ndb.DateTimeProperty()

1 个答案:

答案 0 :(得分:3)

Google AppEngine即使在处理大量数据时速度如此之快的主要原因之一是查询选项非常有限。所有标准查询都是&#34;扫描&#34;在索引上,即有一些表(索引)保持对您的实际数据的引用,并按照数据的一个属性进行排序。所以,我们假设您添加以下条目:

Thing A: start-date = Wednesday (I'm just going to use weekdays for simplicity)
Thing B: start-date = Friday
Thing C: start-date = Monday
Thing D: start-date = Thursday

然后,AppEngine将创建一个如下所示的索引:

1 - Monday    -> Thing C
2 - Wednesday -> Thing A
3 - Thursday  -> Thing D
4 - Friday    -> Thing B

现在,任何查询都将对应于此(或另一个)索引中的连续块。例如,如果您说&#34;所有事情的开始日期&gt; =星期二&#34;,它将返回第2行到第4行中的条目(即Thing A,Thing D和Thing B按照确切的顺序! )。如果您查询&#34;&lt;星期四&#34;,你得到1-2。如果你说&#34;&gt;星期二和&lt; =星期四&#34;你得到2-3。

如果你在不同的属性上做不等式过滤器,AppEngine将使用不同的索引。

这就是为什么你只能做一个不等式过滤器以及为什么排序顺序总是也由你做不等式过滤器的属性指定的原因。因为AppEngine不能设计为能够从索引中返回项目1,2,4(间隙 * ),或者项目4,2,3(没有间隙,但是没有顺序)

因此,如果您需要在不同于您使用不等式过滤的属性的其他属性上对条目进行排序,那么您基本上有3个选择:

  1. 使用不等式过滤器执行查询,将所有结果读入内存,然后在代码中对它们进行排序(我认为这就是将它们存储在字典中的含义)
  2. 在不使用不等式过滤器的情况下执行查询,但按右侧属性排序。然后,当您循环返回的条目时,只需自己检查不等式并删除不匹配的条目
  3. 使用不等式过滤器执行查询,只返回错误顺序的项目,让客户端应用程序担心排序它们! ;)
  4. 通常我会假设您有更多未使用的资源可用于客户端进行排序,因此在大多数情况下我可能会选择3。但是,如果您需要对服务器端的条目进行排序(例如针对较旧的智能手机的移动应用程序),则将取决于数据库的大小以及通常与您的不等式过滤器匹配的条目的比例,无论选项1或选项2更好。如果你的不等式过滤器只删除了一小部分条目,那么选项2可能要快得多(因为它不需要任何O(&gt; n)排序),但是如果你有一个巨大的条目数据库而且只有一个其中很少一部分会与不平等相匹配,一定会选择1。

    BTW:来自Google I / O 2008的谈话"App Engine Datastore Under the Covers"可能是一个非常有用的资源。它有点技术性,但它给出了这个主题的一个很好的概述,如果你想在AppEngine中做任何事情,我认为它必须知道信息。但请注意,这次谈话有点过时了。现在,您可以通过查询进行更多的事情。但所有这些额外的东西(如果我理解正确的话)都是API函数,最终只会生成一组简单的查询(完全类似于本演讲中描述的那些),然后在应用程序中将这些结果合并到内存中(就像你自己进行排序一样)。

    * 有一些例外情况,AppEngine可以生成两个(或更多?)索引扫描的交集,从结果中删除项目,但我不认为您可以使用它来更改返回条目的顺序。