简体   繁体   English

Django 使用 LEFT JOIN 而不是 INNER JOIN

[英]Django use LEFT JOIN instead of INNER JOIN

I have two models: Comments and CommentFlags我有两个模型: CommentsCommentFlags

class Comments(models.Model):
    content_type = models.ForeignKey(ContentType,
                                     verbose_name=_('content type'),
                                     related_name="content_type_set_for_%(class)s",
                                     on_delete=models.CASCADE)
    object_pk = models.CharField(_('object ID'), db_index=True, max_length=64)
    content_object = GenericForeignKey(ct_field="content_type", fk_field="object_pk")
    submit_date = models.DateTimeField(_('date/time submitted'), default=None, db_index=True)
    ...
    ...


class CommentFlags(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="comment_flags",
                             on_delete=models.CASCADE)
    comment = models.ForeignKey(Comment, related_name="flags", on_delete=models.CASCADE)
    flag = models.CharField(max_length=30, db_index=True)
    ...
    ...  

CommentFlags flag can have values: like , dislike etc. CommentFlags flag可以有值: likedislike等。

Problem Statement : I want to get all Comments sorted by number of likes in DESC manner.问题陈述:我想以DESC方式按喜欢的数量排序所有Comments

Raw Query for above problem statement:上述问题陈述的原始查询

SELECT 
    cmnts.*, coalesce(cmnt_flgs.num_like, 0) as num_like
FROM 
    comments cmnts
LEFT JOIN
(
    SELECT 
        comment_id, Count(comment_id) AS num_like 
    FROM 
        comment_flags 
    WHERE 
        flag='like' 
    GROUP BY comment_id 
) cmnt_flgs      
ON 
    cmnt_flgs.comment_id = cmnts.id 
ORDER BY 
    num_like DESC

I have not been able to convert the above query in Django ORM Queryset.我无法在 Django ORM 查询集中转换上述查询。

What I have tried so far...到目前为止我尝试过的...

>>> qs = (Comment.objects.filter(flags__flag='like').values('flags__comment_id')
                         .annotate(num_likes=Count('flags__comment_id')))

which generates different query.这会产生不同的查询。

>>> print(qs.query)
>>> SELECT "comment_flags"."comment_id",
       COUNT("comment_flags"."comment_id") AS "num_likes"
    FROM "comments"
    INNER JOIN "comment_flags"
    ON ("comments"."id" = "comment_flags"."comment_id")
    WHERE "comment_flags"."flag" = 'like'
    GROUP BY "comment_flags"."comment_id",
             "comments"."submit_date"
   ORDER BY "comments"."submit_date" ASC
   LIMIT 21

Problem with above ORM queryset is, it uses InnerJoin and also I don't know how it adds submit_date in groupby clause.上述 ORM 查询集的问题是,它使用InnerJoin ,而且我不知道它如何在groupby子句中添加submit_date

Can you please suggest me a way to convert above mentioned Raw query to Django ORM queryset?您能否建议我将上述原始查询转换为 Django ORM 查询集的方法?

You can try using filter argument in Count :您可以尝试在Count中使用filter参数:

qs = (Comment.objects.all()
      .annotate(num_likes=Count('flags__comment_id', filter=Q(flags__flag='like'))))

It may produce slightly different query that you're expecting, depending on the database backend, but it should have equivalent behavior.根据数据库后端的不同,它可能会产生您所期望的略有不同的查询,但它应该具有相同的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM