Search code examples
djangopostgresqlrelational-databasedjango-related-manager

Django queryset on related field


Django is to making a query much more complicated than it needs to be.

A Sentiment may have a User and a Card, and I am getting the Cards which are not in the passed User's Sentiments

This is the query:

Card.objects.all().exclude(sentiments__in=user.sentiments.all())

this is what Django runs:

SELECT * FROM "cards_card" WHERE NOT ("cards_card"."id" IN ( SELECT V1."card_id" AS "card_id" FROM "sentiments_sentiment" V1 WHERE V1."id" IN ( SELECT U0."id" FROM "sentiments_sentiment" U0 WHERE U0."user_id" = 1 ) ) )

This is a version I came up with which didn't do an N-Times full table scan:

Card.objects.raw(' SELECT DISTINCT "id" FROM "cards_card" WHERE NOT "id" IN ( SELECT "card_id" FROM "sentiments_sentiment" WHERE "user_id" = ' + user_id + ' ) )')

I don't know why Django has to do it with the N-Times scan. I've been scouring the web for answers, but nothing so far. Any suggestions on how to keep the performance but not have to fall back to raw SQL?


Solution

  • A better way of writing this query without the subqueries would be:

    Card.objects.all().exclude(sentiments__user__id=user.id)