2011-06-23 83 views
0

我希望標題沒有誤導性。根據m2m字段進行查詢的匹配數量

無論如何,我有兩個模型,都與第三個模型有m2m關係。

class Model1: keywords = m2m(Keyword) 
class Model2: keywords = m2m(Keyword) 

鑑於一個模型2實例的關鍵字是這樣的:

keywords2 = model2_instance.keywords.all() 

我需要找回它至少有一個關鍵字是keywords2,類似的型號1實例:

Model1.objects.filter(keywords__in=keywords2) 

並按匹配關鍵字的數量對它們進行排序(不要認爲它可能通過'in'字段查找)。問題是,我該怎麼做?

我想通過每個Model1實例手動進行交互,將它們追加到每個匹配結果的字典中,但是我需要這樣來擴展,比如說成千上萬的記錄。這裏是我想象它會像:

result = {} 
keywords2_ids = model2.keywords.all().values_list('id',flat=True) 
for model1 in Model1.objects.all(): 
    keywords_matched = model1.keywords.filter(id__in=keywords2_ids).count() 
    objs = result.get(str(keywords_matched), []) 
    result[str(keywords_matched)] = objs.append(obj) 

必須有這樣做的更快的方法。有任何想法嗎?

回答

2

您可以切換到原始SQL。你需要做的是寫一個自定義managerModel1根據關鍵字匹配計數返回Model1對象的有序ID集合。 SQL很簡單,因爲在關鍵字ID上加入兩個多對多表(Django自動創建表來表示多對多關係),然後在Model1 ID上對COUNT sql函數進行分組。然後在這些計數上使用ORDER BY子句將產生您需要的排序的Model1 id列表。在MySQL中,

SELECT appname_model1_keywords.model1_id, count(*) as match_count FROM appname_model1_keywords 
JOIN appname_model2_keywords 
ON (appname_model1_keywords.keyword_id = appname_model2_keywords.keyword_id) 
WHERE appname_model2_keywords.model2_id = model2_object_id 
GROUP BY appname_model1_keywords.model1_id 
ORDER BY match_count 

這裏model2_object_idmodel2_instance ID。這肯定會更快,更具可擴展性。

相關問題