下面的代碼實現歐文的回答上述(使用BETWEEN
),用於一個Django查詢集:
甲效用函數,將對於任意的Django查詢集爲此如下。它默認假設'id'是一個合適的字段,用於between
子句。
def chunked_queryset(qs, batch_size, index='id'):
"""
Yields a queryset split into batches of maximum size 'batch_size'.
Any ordering on the queryset is discarded.
"""
qs = qs.order_by() # clear ordering
min_max = qs.aggregate(min=models.Min(index), max=models.Max(index))
min_id, max_id = min_max['min'], min_max['max']
for i in range(min_id, max_id + 1, batch_size):
filter_args = {'{0}__range'.format(index): (i, i + batch_size - 1)}
yield qs.filter(**filter_args)
它會像這樣使用:
for chunk in chunked_queryset(SomeModel.objects.all(), 20):
# `chunk` is a queryset
for item in chunk:
# `item` is a SomeModel instance
pass
這假定記錄以相同的順序沒有'sort'條款返回。它是否正確?另外,如果我在我的'Meta'類中有一個默認的排序,我可以以某種方式刪除它的查詢? – Joe 2012-01-03 12:41:17
@Joe:基本上你會得到相同的記錄,但是沒有排序。如果您的ID空間存在空白,則每次調用返回的記錄數量可能會少於預期。使用LIMIT/OFFSET時,您會得到固定數量的排序行(每個表格最後一次調用除外)。我不怎麼處理'Meta'類,但是你需要*爲你的行排列LIMIT/OFFSET。 – 2012-01-03 14:09:23
埃爾文,我真的很抱歉,我沒有正確地讀你的答案。你確定這更快嗎?只要id已經被排序,或者每次執行整個表掃描,''between''子句肯定只能工作。 – Joe 2012-01-03 15:27:52