Django intersect count annotate for sorting

情到浓时终转凉″ 提交于 2019-12-11 06:29:09

问题


In this question, we were given a solution to sort a query based on the intersection of two many to many fields. While it's a great answer, the restriction is that you have to filter first.

Say I have the same two models. Is there a way to annotate all results by count of intersection, so that I can display all Questions regardless of location, but still sorted by location?

class Location(models.Model):
    name = models.CharField(max_length=100)


class Profile(models.Model):
    locations_of_interest = models.ManyToManyField(Location)


class Question(models.Model):
    locations = models.ManyToManyField(Location)

I wish I could do something like this:

from django.db.models import Count

matching_profiles = Profile.objects.all().annotate(
    locnom=Count('locations_of_interest__in=question.locations.all()')
)

Any ideas? Do I just have to make two queries and merge them?


回答1:


We can move the filtering in the Count function as well:

Profile.objects.annotate(
    locnom=Count('id', filter=Q(locations_of_interest__in=question.locations.all()))
)

The two are not equivalent in the sense that Profiles with no related Locations, or in case the question has no location, will still be included, in that case the .locnom of that Profile will be 0.

The query looks approximately like:

SELECT profile.*,
       COUNT(CASE WHEN proloc.location_id IN (1, 4, 5) THEN profile.id ELSE NULL)
           AS locnom
FROM profile
LEFT OUTER JOIN profile_locations_of_interest AS proloc
             ON profile.id = proloc.profile_id
GROUP BY profile.id

Where [1, 4, 5] are here sample ids of the related Locations of the question.




回答2:


try to use subquery https://docs.djangoproject.com/fr/2.0/ref/models/expressions/#subquery-expressions

Like this example: https://books.agiliq.com/projects/django-orm-cookbook/en/latest/subquery.html

from django.db.models import Subquery
users = User.objects.all()
UserParent.objects.filter(user_id__in=Subquery(users.values('id')))


来源:https://stackoverflow.com/questions/51504634/django-intersect-count-annotate-for-sorting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!