2016-08-06 9 views
0

Ich versuche, Zeilen aus einer Tabelle zu erhalten, deren Einträge die meisten Übereinstimmungen in einer anderen Tabelle aufweisen, auf die mit einem Feld manytomany verwiesen wird.Django-Filtertabelle und sortieren nach Anzahl

Die SQL, das funktioniert ist:

SELECT *, COUNT(*) FROM events_event_genres 
LEFT JOIN events_event 
ON event_id = events_event.id 
WHERE genre_id IN (6,9,31) 
AND start_date > '2016-08-06' 
GROUP BY event_id 
ORDER BY COUNT(*) DESC 
LIMIT 10 

Das Ereignismodell hat:

class Event(models.Model): 
    title = models.CharField(max_length=250) 
    start_date = models.DateTimeField() 
    genres = models.ManyToManyField("genres.Genre", blank=True, null=True, related_name="events") 

Aus meiner Sicht habe ich versucht:

results = Event.objects.filter(
    Q(genres__id__in=genres), 
    Q(start_date__gte=datetime.date.today()) \ 
    .annotate(event=Count('id')) \ 
    .order_by('event') 

Die Ergebnisse erhalte ich fast das gleiche wie diese SQL-Abfrage:

SELECT * FROM events_event 
LEFT JOIN events_event_genres 
ON events_event.id = event_id 
WHERE genre_id IN (6,9,31) 
AND start_date > '2016-08-06' 
LIMIT 10 

So eindeutig funktioniert die Zählung nicht.

Was ist der Django-Weg, dies zu tun?

+0

Können Sie eine einfache englische Version von dem, was gewünschte Ergebnis? Der Versuch, Ihr SQL zurückzuentwickeln, ist nicht einfach. – solarissmoke

+0

Sicher. Ich versuche, alle Ereignisse zu erhalten, die mit einer Liste von Genres übereinstimmen, und zähle dann, wie viele Übereinstimmungen jedes Ereignis hat. Ich möchte alle Ereignisse zurückgeben, die zu mindestens einem der Genres passen, aber nach der Anzahl der Übereinstimmungen sortiert sind, die jedes Ereignis hat. – James

Antwort

1

Sie sind nicht weit entfernt. Diese Abfrage sollte funktionieren:

Event.objects.filter(genres__in=genres, start_date__gte=datetime.date.today())\ 
.distinct().annotate(num_genres=Count('genres')).order_by('-num_genres') 

Jedes Event Objekt in der resultierenden queryset eine num_genres Eigenschaft mit einer Zählung der Anzahl von Genres, die abgestimmt. Sie werden nach der Anzahl der passenden Genres geordnet.

Die resultierende SQL ist:

SELECT DISTINCT "events_event"."id", "events_event"."name", 
COUNT("events_event_genres"."genre_id") AS "n" 
FROM "events_event" INNER JOIN "events_event_genres" 
ON ("events_event"."id" = "events_event_genres"."event_id") 
WHERE "events_event_genres"."genre_id" IN (g1) 
GROUP BY "events_event"."id", "events_event"."name" 
ORDER BY "n" DESC 
+0

Danke, das funktioniert gut! – James

Verwandte Themen