4

我正在寻找类似于 reddit/hackernews 具体如何处理他们的“新”列表的东西(这似乎是许多主要网站的常用方法)。它似乎像这样工作:

  • 提交新链接时,抓取一定数量的最新条目
  • 这些查询由 PER_PAGE # 划分并缓存为 cachekey = latestPage1,2,3,4
  • 单击下一个/上一个按钮加载下一个/上一个缓存键

我的问题是:很难找到 SQLalchemy/flask-sqlalchemy 代码来获取仅固定 # 的最新条目的查询。

我怎么说:

q = PostDB.query(order_by('creation_time').desc()).limit(1000)
for chunkOf50Results in q:
  cache.set(CachedChunk+=1, chunkOf50Results)

?

4

2 回答 2

4

如果您在 SQLAlchemy 中对查询进行切片,它会自动限制获取的数据库结果集:

limitedQuery = q[:50]

如果您要先进行计数,则可以轻松地循环分块响应:

count = q.count()
for chunkstart in xrange(0, count, 50):
    CachedChunk += 1
    chunkend = min(chunkstart + 50, count)
    cache.set(CachedChunk, q[chunstart:chunkend])

请注意,这确实会导致对数据库的多次查询。或者,您可以使用该itertools.izip_longest()函数生成 50 个项目的组:

from itertools import izip_longest

for chunkOf50Results in izip(*[q.yield_per(50)]*50):
     CachedChunk += 1
     cache.set(CachedChunk, chunkOf50Results)

我曾经.yield_per(50)将行预取限制为批量大小,因此您不会预取超过每批所需的数量。

izip_longest(*[iterable]*n)技巧为您提供n了基本迭代器之外的大小组:

>>> import itertools
>>> list(itertools.izip_longest(*[iter(range(7))]*3))
[(0, 1, 2), (3, 4, 5), (6, None, None)]

请注意,最后一批填充了None值以填充到批量大小。

于 2012-08-24T16:13:57.163 回答
2

解决方案是使用文档中描述itertools.izip_longest的技巧

q = PostDB.query(order_by('creation_time').desc()).limit(1000)

query_iterators = [iter(q)] * 50

for CachedChunk, chunk_of_50 in enumerate(izip_longest(*query_iterators)):
     cache.set(CachedChunk, chunk_of_50)

应该会导致一次访问数据库获取多达 1000 篇文章,然后让您将它们分成 50 个批次并缓存它们。

于 2012-08-24T16:34:39.853 回答