逻辑或 Django 多对多查询返回重复结果

Posted

技术标签:

【中文标题】逻辑或 Django 多对多查询返回重复结果【英文标题】:Logical or of Django many to many queries returns duplicate results 【发布时间】:2011-12-06 02:57:03 【问题描述】:

我有这样的多对多关系模型:

class Contact(models.Model):
    name = models.TextField()
    address = models.TextField()

class Mail(models.Model):
    to = models.ManyToManyField(Contact, related_name='received_mails')
    cc = models.ManyToManyField(Contact, related_name='cced_mails')

我想获取给定电子邮件的收件人字段或抄送字段中的一组联系人。让我们试试吧:

>>> Contact.objects.filter(received_mails__id=111)
[<Contact: fred@foo.com>]
>>> Contact.objects.filter(cced_mails__id=111)
[<Contact: joe@bar.com>]

到目前为止一切顺利。每个关系我们都有一个联系人。但是将它们都放入同一个查询集中会很好。

>>> Contact.objects.filter(Q(received_mails__id=111) | Q(cced_mails__id=111))
[<Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, <Contact: joe@bar.com>, '...(remaining elements truncated)...']

发生了什么?我有一种感觉,这与在 SQL 中连接表有关,但我真的不明白在多对多关系的背后发生了什么。可能是我想做的事情很愚蠢,或者有一种简单的方法可以做到。不管怎样,我很高兴能走上正确的道路。

编辑:这是 QuerySet 的查询:

SELECT `mailshareapp_contact`.`id`, `mailshareapp_contact`.`name`,
`mailshareapp_contact`.`address` FROM `mailshareapp_contact`
LEFT OUTER JOIN `mailshareapp_mail_to`
ON (`mailshareapp_contact`.`id` = `mailshareapp_mail_to`.`contact_id`)
LEFT OUTER JOIN `mailshareapp_mail_cc`
ON (`mailshareapp_contact`.`id` = `mailshareapp_mail_cc`.`contact_id`)
WHERE (`mailshareapp_mail_to`.`mail_id` = 111
OR `mailshareapp_mail_cc`.`mail_id` = 111 )

【问题讨论】:

【参考方案1】:

由于 SQL 返回所有匹配的记录,Django 尽职尽责地将它们映射到对象。您正在寻找的是 .distinct() queryset 方法,该方法使 SQL 将所有重复的行合并为一个。

【讨论】:

成功了,谢谢。 (抱歉,我还不能投票给你。)这会通过使用 SELECT DISTINCT 而不仅仅是 SELECT 来更改查询。我不明白没有它你怎么能得到这么多个重复,但我的直接问题已经解决了。 对于满足至少一个 JOIN 和一个 WHERE 的 mailshareapp_contact × (mailshareapp_mail_to + NULL) × (mailshareapp_mail_cc + NULL) 的每个组合,您将获得一个单独的行条款。顺便说一句,如果以上回答了您的问题,您可以随时将其标记为已接受的回复。

以上是关于逻辑或 Django 多对多查询返回重复结果的主要内容,如果未能解决你的问题,请参考以下文章

多对多的 Django Inline 生成重复查询

Django查询集获得精确的多对多查询[重复]

如何在双连接关系之后在 Django 中执行查询(或:如何绕过 Django 对多对多“通过”模型的限制?)

多对多字段返回无 django

Python学习第135天(Django的ORM多对多查询)

如何在 django 中过滤查询集的多对多