如何获取超过1000?

我怎样才能从数据存储中获取超过1000条logging,并把所有在一个单一的列表传递给Django?

从版本1.3.6(2010年8月17日发布)开始,您可以

从更新日志:

所有数据存储查询的数据存储计数()查询和偏移结果不再限制在1000

只是为了纪录 – 1000个条目的获取限制现在已经消失:

http://googleappengine.blogspot.com/2010/02/app-engine-sdk-131-including-major.html

报价:

不超过1000个结果限制 – 没错,在过去的几个月中,除了增加了游标以及许多较小的数据存储稳定性和性能改进之外,我们现在已经足够有信心完全消除最大结果限制。 无论您是在进行读取,迭代还是使用光标,对结果的数量都没有限制。

App Engine为您提供了一个很好的方式,通过在Keys上sorting,通过结果“分页”,并使用最后一个键作为下一个偏移量。 他们甚至在这里提供一些示例代码:

http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Queries_on_Keys

尽pipe他们的示例将查询分散到很多请求上,但您可以将页面大小从20更改为1000,然后结合查询集循环查询。 此外,您可能会使用itertools来链接查询,而无需在需要之前进行评估。

例如,要计算超过1000行的行数:

class MyModel(db.Expando): @classmethod def count_all(cls): """ Count *all* of the rows (without maxing out at 1000) """ count = 0 query = cls.all().order('__key__') while count % 1000 == 0: current_count = query.count() if current_count == 0: break count += current_count if current_count == 1000: last_key = query.fetch(1, 999)[0].key() query = query.filter('__key__ > ', last_key) return count 

每当这种情况出现时,我总是想知道“ 为什么你需要超过1000个结果?” 你知道Google自己没有提供超过1000个结果吗? 试试这个search: http : //www.google.ca/search?hl= zh-CN&client=firefox-a&rls=org.mozilla: en- US: official& hs=qhu&q=1000+results&start=1000&sa= N直到我才知道最近,因为我从来没有花时间点击进入查询search结果的第100页。

如果您实际上将超过1,000条结果返回给用户,那么我认为手头上的问题比数据存储不会让您这样做的事实更大。

需要这么多结果的一个可能的(合理的)理由是,如果您对数据进行了大量的操作并显示一个摘要(例如,所有这些数据的平均值是多less)。 这个问题的解决scheme(在Google I / O谈话中讨论过)是在即时计算汇总数据并将其保存下来。

你不能。

部分常见问题表明,您无法访问查询的第1000行之外的数据,增加“OFFSET”只会导致更短的结果集,

即:OFFSET 999 – > 1结果返回。

维基百科:

App Engine将实体返回的最大行数限制为每个数据存储区调用1000行。 大多数Web数据库应用程序使用分页和caching,因此一次不需要这么多的数据,所以这在大多数情况下是不成问题的。如果应用程序每个操作需要超过1,000条logging,则可以使用它自己的客户端软件或Ajax页面来执行无限数量的行上的操作。

来自http://code.google.com/appengine/docs/whatisgoogleappengine.html

服务限制的另一个示例是查询返回的结果数量。 查询最多可以返回1000个结果。 将返回更多结果的查询只返回最大值。 在这种情况下,执行这样的查询的请求不太可能在超时之前返回请求,但是限制已经到位以节省数据存储上的资源。

http://code.google.com/appengine/docs/datastore/gqlreference.html

注:LIMIT子句的最大值为1000.如果指定了大于最大值的限制,则使用最大值。 这个相同的最大值适用于GqlQuery类的fetch()方法。

注意:与fetch()方法的offset参数一样,GQL查询string中的OFFSET不会减less从数据存储中获取的实体的数量。 它只影响fetch()方法返回的结果。 具有偏移量的查询具有与偏移量大小线性对应的性能特征。

http://code.google.com/appengine/docs/datastore/queryclass.html

limit和offset参数控制从数据存储中获取的结果数量,以及fetch()方法返回的结果数量:

  • 数据存储将偏移+限制结果提取到应用程序。 数据存储本身不会跳过第一个偏移量结果。

  • fetch()方法跳过第一个偏移量结果,然后返回其余(限制结果)。

  • 查询具有与偏移量加上限制线性对应的性能特征。

这意味着什么

如果您有单个查询,则无法请求0-1000范围之外的任何内容。

增加偏移量只会提高0,所以

 LIMIT 1000 OFFSET 0 

将返回1000行,

 LIMIT 1000 OFFSET 1000 

将返回0行 ,因此,使用单个查询语法无法手动或使用API​​获取2000个结果。

唯一可能的例外

是在表上创build一个数字索引,即:

  SELECT * FROM Foo WHERE ID > 0 AND ID < 1000 SELECT * FROM Foo WHERE ID >= 1000 AND ID < 2000 

如果你的数据或查询不能有这个“ID”硬编码的标识符,那么你运气不好

这个1K限制问题已解决。

 query = MyModel.all() for doc in query: print doc.title 

将Query对象视为一个可迭代对象:迭代器以小批量方式从数据存储中检索结果,从而允许应用程序停止对结果进行迭代,以避免获取超出需要的数据。 当所有匹配查询的结果都被检索到时,迭代停止。 与fetch()一样,迭代器接口不caching结果,因此从Query对象创build一个新的迭代器将重新执行查询。

最大批量为1K。 而且你还有自动数据存储配额。

但是对于1.3.1 SDK计划,他们引入了可以序列化和保存的游标,以便将来的调用可以开始查询。

1000个logging限制是Google AppEngine中的一个硬性限制。

此演示文稿http://sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine解释了如何使用AppEngine有效地翻阅数据。;

(基本上通过使用一个数字ID作为关键,并在ID上指定一个WHERE子句。)

抓取虽然远程API仍然有超过1000条logging的问题。 我们编写了这个小函数来遍历一个块:

 def _iterate_table(table, chunk_size = 200): offset = 0 while True: results = table.all().order('__key__').fetch(chunk_size+1, offset = offset) if not results: break for result in results[:chunk_size]: yield result if len(results) < chunk_size+1: break offset += chunk_size 

我们在ModelBase类中使用了一些东西:

 @classmethod def get_all(cls): q = cls.all() holder = q.fetch(1000) result = holder while len(holder) == 1000: holder = q.with_cursor(q.cursor()).fetch(1000) result += holder return result 

这可以避免每个模型1000个查询限制,而无需考虑这个限制。 我猜想一个密钥版本将会很容易实现。

 class Count(object): def getCount(self,cls): class Count(object): def getCount(self,cls): """ Count *all* of the rows (without maxing out at 1000) """ count = 0 query = cls.all().order('__key__') while 1: current_count = query.count() count += current_count if current_count == 0: break last_key = query.fetch(1, current_count-1)[0].key() query = query.filter('__key__ > ', last_key) return count 
 entities = [] for entity in Entity.all(): entities.append(entity) 

就那么简单。 请注意,每个实体都有一个RPC,比块中的获取要慢得多。 所以如果你关心性能,请执行以下操作:

如果您的项目less于1M个:

 entities = Entity.all().fetch(999999) 

否则,请使用游标。

还应该指出的是:

 Entity.all().fetch(Entity.all().count()) 

返回1000最大值,不应使用。

JJG:上面的解决scheme非常棒,除非它有0条logging,否则会导致无限循环。 (我在本地testing了一些报告的时候发现了这个)。

我修改了while循环的开始,如下所示:

 while count % 1000 == 0: current_count = query.count() if current_count == 0: break 

要一起添加两个查询的内容:

 list1 = first query list2 = second query list1 += list2 

清单1现在包含所有2000个结果。

build议的解决scheme只有在条目按键sorting的情况下才有效。如果先按另一列sorting,则仍然需要使用限制(offset,count)子句,则1000条目限制仍然适用。 如果使用两个请求,一个用于检索索引(使用条件和sorting),另一个使用索引in()和第一个结果的索引子集,因为第一个请求不能返回超过1000个密钥? (“Google 键盘上的查询”部分没有明确说明是否必须按键sorting才能删除1000个结果限制)

这与Gabriel提供的解决scheme非常接近,但是并没有提取结果:

 count = 0 q = YourEntityClass.all().filter('myval = ', 2) countBatch = q.count() while countBatch > 0: count += countBatch countBatch = q.with_cursor(q.cursor()).count() logging.info('Count=%d' % count) 

完美的工作,我的查询,也快(1.1秒计数67,000个实体)

请注意,查询不能是不等式筛选器或集合,否则游标将不起作用,您将得到以下exception:

AssertionError:MultiQuery没有可用的游标(查询使用“IN”或“!=”运算符)

如果您使用NDB:

 @staticmethod def _iterate_table(table, chunk_size=200): offset = 0 while True: results = table.query().order(table.key).fetch(chunk_size + 1, offset=offset) if not results: break for result in results[:chunk_size]: yield result if len(results) < chunk_size + 1: break offset += chunk_size