2017-11-14 2 views
0

Der folgende Funktionsrang zählt die Eltern in der Datenbank richtig, aber ich muss es wie Group.query senden. (User_id == 1) .rank (0, Group.query. (user_id == 1)) das scheint nicht sehr effizient zu sein. Gibt es eine bessere Möglichkeit, diese Funktion zu schreiben?sqlalchemy versucht, Eltern in der Datenbank effizient zu zählen

+0

Mit anderen Worten versuchen Sie, die Verschachtelungsebene zu zählen? Welche DB benutzen Sie? Warum übergeben Sie die selbe Instanz wie das Argument "parent" an "rank()", anstatt "self" zu verwenden? –

+0

Ich benutze sqlite für die Datenbank. Ich habe versucht, selbst zu verwenden, aber es immer wieder 0. Meine Idee ist, wenn Sie 5 Eltern haben Ihren Rang 5. Da die Datenbank selbst Referencial ist brauche ich diese in der Lage zu ändern, wenn eine neue scheinbare als Wurzel angehängt ist. –

Antwort

2

Das Übergeben der Instanz, für die Sie die Methode aufrufen, als ein weiteres Argument ist redundant, und Ihrer Funktion fehlt auch eine return-Anweisung. Ganz zu schweigen von der zweimaligen Ausführung derselben Abfrage, nur um loszulegen. Sie könnten und sollten einfach self und self.parent verwenden. Ihre rekursive Funktion des Basisfall wäre, wenn kein Elternteil:

class Group(db.Model): 

    def rank(self): 
     if not self.parent: 
      return 0 

     else: 
      # Python has no TCO, so no point in trying to 
      # use an accumulator 
      return 1 + self.parent.rank() 

Aber Sie haben Recht, dass dies im Idealfall nicht durchführen könnte, wenn Sie tief verschachtelte Strukturen haben, aber nur für ein paar Ebene der Verschachtelung der einfache Rekursion könnte komplexere Methoden schlagen. Jeder erste Zugriff von Group.parent auf eine Instanz wird eine neue SELECT-Anweisung an die DB ausgeben. Sie könnten die Operation zu Ihren Daten führen, oder mit anderen Worten, sie in der Datenbank ausführen. Baum artige Strukturen mit einem recursive Common Table Expression behandelt werden:

def rank(self): 
    cls = type(self) 
    parents = db.session.query(cls.parent_id).\ 
     filter_by(id=self.id).\ 
     cte(recursive=True) 

    parent_alias = db.aliased(parents) 
    group_alias = db.aliased(cls) 

    parents = parents.union_all(
     db.session.query(group_alias.parent_id). 
      filter(group_alias.id == parent_alias.c.parent_id)) 

    # Subtract one so that only the parents count 
    return db.session.query(db.func.count() - 1).\ 
     select_from(parents).\ 
     scalar() 

Sie können diese möglicherweise wiederum in ein hybrid property, wenn Sie die Zählung SQL-Seite einige Zeit brauchen.

+0

Stark ist der Python in diesem. –

Verwandte Themen