Need to annotate Django querySet based on which Q

2019-08-30 04:38发布

问题:

So I have a query with a few Q objects that are OR-ed together (to achieve a UNION), and I want to annotate each result with which Q object was a match. This is so when I go to display my query results, I can highlight which search term(s) were hits on each result.

Here's the code that produces the resulting querySet:

Gene.objects.filter(Q(EC__EC='3.2.1.4')|Q(Protein_Family__name__in=famList)|Q(Pfam__Pfam__in=pfams),Protein_length__gte=100, Distance_From_Contig_Upstream__gte=10, Distance_From_Contig_Downstream__gte=10).distinct()

I think I can add this annotated column using the .extra option: https://docs.djangoproject.com/en/1.3/ref/models/querysets/#extra

If I can't do this, I will probably do three separate queries, then annotate the results, then OR the querysets together... I think this is probably pretty wasteful, and seems clumsy.

回答1:

If you annotate with extra, the final distinct won't work. If you have one record (in the JOINed table) matching the condition on EC and another matching the condition on Protein.Family.name, then it either gives you one of the matching records (so it will add only the corresponding flag) or it gives you all matching record (duplicating the results in the result set).