Optimiere zwei SQL-Abfragen und ein Listenverständnis

Ich habe diese beiden Modelle (vereinfacht):

class Place(OrderedModel): name = models.CharField(max_length=100) class Team(models.Model): name = models.CharField(max_length=100) places = models.ManyToManyField(Place, blank=True) 

Sagen Sie, dass es zehn Instanzen von Place . Aber nur fünf Instanzen des Team . Ich möchte eine Liste von Booleschen in der Reihenfolge der Einträge in Place , wo True bedeutet, dass Team.places diesen Platz enthält und False (offensichtlich) bedeutet, dass es nicht geht. Das Team.places Feld hat keine besondere Bestellung.

Im folgenden Beispiel hat das Team die Instanzen der ersten vier Place und das letzte in seinem places :

 [True, True, True, True, False, False, False, False, False, True] 

Ich habe das mit dieser Methode auf das Team-Modell gelöst:

 class Team(models.Model): ... def done(self): """ Returns a list of Booleans, one for each place in order. True means that the team has found the place. False, that they have not. """ places = Place.objects.all() return [p in self.places.all() for p in places] 

Es funktioniert aber scheint sehr ineffizient. Es macht (glaube ich) zwei verschiedene SQL-Abfragen und dann ein Listenverständnis. Gibt es eine effizientere Möglichkeit, dies zu lösen?

Gelöst

Ich habe es am Ende gemacht:

 def done(self): """ Returns a list of Booleans, one for each place in order. True means that the team has found the place. False, that they have not. """ sql = '''SELECT P.id, (TP.id IS NOT NULL) AS done FROM qrgame_place P LEFT OUTER JOIN qrgame_team_places TP ON P.id = TP.place_id AND TP.team_id = %s''' places = Place.objects.raw(sql, [self.id]) for p in places: yield bool(p.done) 

2 Solutions collect form web for “Optimiere zwei SQL-Abfragen und ein Listenverständnis”

Sie benötigen diese SQL-Abfrage:

 SELECT P.id, (TP.id IS NOT NULL) AS done FROM myapp_place P LEFT OUTER JOIN myapp_team_places TP ON P.id = TP.place_id AND TP.team_id = %s 

(Du musst auch eine ORDER BY Klausel hinzufügen, um die Place Objekte in der gewünschten Reihenfolge zurückzugeben, aber da ich diesen Teil deines Modells nicht sehen kann, kann ich nicht sagen, wie diese Klausel aussehen soll.)

Ich weiß nicht, wie man diese Abfrage mit Djangos Objekt-relationalen Mapping-System ausdrücken kann, aber man kann es immer mit einer Roh-SQL-Abfrage ausführen:

 >>> sql = ''' ... as above ... ''' >>> places = Place.objects.raw(sql, [team.id]) >>> for p in places: ... print p.id, bool(p.done) ... 1 True 2 True 3 False 

Eine optimale Lösung wäre:

 def done(self): places = Place.objects.values_list('pk', flat=True) team_places = self.places.values_list('pk', flat=True) return [place in team_places for place in places] 
  • Code optimieren durch sympy
  • Python-Äquivalent von MATLABs "ismember" -Funktion
  • Optimierung der Punkt-Kreis-Distanzmethode
  • Schnelle Tensorrotation mit NumPy
  • Globaler vs. lokaler Namensraum Leistungsunterschied
  • Python Performance Verbesserung Anfrage für Winkler
  • Wie wähle man viele bis eins zu vielen ohne Hunderte von Abfragen mit Django ORM?
  • Numpy: Broadcast-Multiplikation über eine gemeinsame Achse von zwei 2d Arrays
  • Kann ich diesen Python-Code vektorisieren?
  • Erhalten eines Fehlers "konnte das Eingabefeld aus der Form (252,4) nicht in Form (4) in der Optimierung übertragen
  • Probleme mit scipy.optimize mit Matrix als Eingabe, Grenzen, Einschränkungen
  • Python ist die beste Programmiersprache der Welt.