2011-06-23 11 views
0

タイトルが誤解を与えないことを願っています。m2mフィールドに基づくクエリの一致数で並べ替え

とにかく、私は2つのモデルを持っていて、どちらも第3のモデルとm2mの関係を持っています。このようなモデル2インスタンスのキーワードを考える

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

:私はkeywords2である少なくともキーワードを持つMODEL1インスタンスを取得する必要が

keywords2 = model2_instance.keywords.all() 

、のようなもの:

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に切り替えることができます。あなたがしなければならないのは、Model1のためにカスタムmanagerを書いて、キーワード一致カウントに基づいてModel1オブジェクトのIDのソートされたセットを返すことです。 SQLは、2つの多対多テーブルを結合することで簡単です(Djangoは多対多の関係を表すテーブルを自動的に作成します)。COUNT SQL関数のModel1 IDでグループ化します。これらのカウントにORDER BY句を使用すると、必要なIDリストのソート済みModel1が生成されます。 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です。これは間違いなく高速でスケーラビリティが高いでしょう。

関連する問題