我希望这个标题不会产生误导。
无论如何,我有两个模型,都与第三个模型有m2m关系。
class Model1: keywords = m2m(Keyword)
class Model2: keywords = m2m(Keyword)
给出Model2实例的关键字如下:
keywords2 = model2_instance.keywords.all()
我需要检索至少包含关键字2中的关键字的Model1实例,例如:
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)
必须有更快的方法来做到这一点。有什么想法吗?
答案 0 :(得分:2)
您可以切换到原始SQL。您要做的是为Model1
编写自定义manager,以根据关键字匹配计数返回Model1对象的有序ID组。 SQL很简单,就是在关键字id上连接两个多对多的表(Django自动创建一个表来表示多对多的关系),然后在{1} sql函数的Model1 id上进行分组。然后在这些计数上使用COUNT
子句将生成所需的已排序ORDER BY
id列表。在MySQL中,
Model1
此处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_id
ID。这肯定会更快,更具可扩展性。