我有以下方式Django模型建立:Django的查詢一大批關係
模型中的有一個一對多的關係模型B
A中的每個記錄有間3000〜15000 B中的記錄
構建一個查詢的最佳方法是什麼,它將檢索B中對應於A中每個記錄中A記錄的最新(最大pk)記錄?這是我必須使用SQL來代替Django ORM嗎?
我有以下方式Django模型建立:Django的查詢一大批關係
模型中的有一個一對多的關係模型B
A中的每個記錄有間3000〜15000 B中的記錄
構建一個查詢的最佳方法是什麼,它將檢索B中對應於A中每個記錄中A記錄的最新(最大pk)記錄?這是我必須使用SQL來代替Django ORM嗎?
安全地提取「頂」創建一個輔助函數來自任何查詢集的項目。我在我自己的Django應用程序中使用它。
def top_or_none(queryset):
"""Safely pulls off the top element in a queryset"""
# Extracts a single element collection w/ top item
result = queryset[0:1]
# Return that element or None if there weren't any matches
return result[0] if result else None
這使用了一點技巧w/slice operator to add a limit clause onto your SQL。
現在,您可以在需要獲取查詢集的「頂部」項目的任何位置使用此功能。在這種情況下,你想要得到的高音B項爲給定的A,其中的B的被降PK排序,例如:
latest = top_or_none(B.objects.filter(a=my_a).order_by('-pk'))
也有在Django Aggregation最近添加的「最大」的功能,可以幫助您得到最大pk,但我不喜歡這種解決方案,因爲它增加了複雜性。
P.S.我不太喜歡依賴這種查詢的'pk'字段,因爲有些RDBMS不能保證順序pks與邏輯創建順序相同。如果我有一張表,我知道我需要以這種方式查詢,我通常有我自己的「創建」日期時間列,我可以使用它來代替pk進行排序。
編輯基於評論:
如果你想用的查詢集[0],可以修改正是如此的 'top_or_none' 功能:
def top_or_none(queryset):
"""Safely pulls off the top element in a queryset"""
try:
return queryset[0]
except IndexError:
return None
我起初並沒有提出這個因爲我的印象是queryset [0]會撤回整個結果集,然後取第0項。顯然,Django在這種情況下也添加了「LIMIT 1」,所以它是我的切片版本的安全替代品。
編輯2
當然,你也可以利用Django的相關管理者的構建這裏通過你的「A」的對象創建的查詢集,根據自己的喜好:
latest = top_or_none(my_a.b_set.order_by('-pk'))
我不認爲Django ORM可以做到這一點(但我之前一直驚喜......)。如果有一個合理數量的A記錄(或者如果你是分頁),我只需要向A模型添加一個方法,它將返回這個'最新'的B記錄。如果你想獲得大量的A記錄,每個記錄都有自己最新的B,那麼我會選擇SQL。
remeber,無論你採取哪條路線,你需要基於B表合適複合指數,也許增加一個order_by=('a_fk','-id')
到Meta
子
什麼 result = queryset [0:1] 和 result = queryset [0]之間的差異? – hekevintran 2009-08-19 02:37:21
queryset [0:1]在沒有匹配的項目時將返回空列表,而queryset [0]將拋出IndexError。 – 2009-08-19 13:48:04
感謝您的回答! – hekevintran 2009-08-19 15:22:30