如何获取超过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中的一个硬性限制。
(基本上通过使用一个数字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