2014-06-24 14 views
8

Versuch, eine Viele-zu-Viele-Beziehung mit ndb zu modellieren. Kann jemand auf ein gutes Beispiel hinweisen, wie man das macht?Viele-zu-viele Beziehungen in ndb

An hier ist ein Beispiel dafür, was ich im Moment habe:

class Person(ndb.Model): 
    guilds = ndb.KeyProperty(kind="Guild", repeated=True) 

class Guild(ndb.Model) 
    members = ndb.KeyProperty(kind="Person", repeated=True) 

    def add_person(self, person): 
     self.members.append(person.key) 
     self.put() 
     person.guilds.append(self.key) 
     person.put() 

Ist dies der richtige Weg, um darüber zu gehen? Ich habe mich gut umgesehen, kann aber keine gute Dokumentation zu diesem Thema finden.

Im Datenspeicher-Viewer kann ich sehen, dass diese Beziehung als Liste der Schlüssel gespeichert wird, was ich erwarte.

Allerdings, wenn ich versuche, sie in der Person-Klasse Methoden zu verwenden, wie folgt aus:

for guild in self.guilds: 

ich:

TypeError: 'KeyProperty' object is not iterable 
+0

'für die Gilde in self.guilds' sollte funktionieren. Überprüfen Sie, ob Sie 'repeated = True' in Person setzen:' gildens = ndb.KeyProperty (kind = "Guild", repeated = True) ' –

+0

Beachten Sie, dass es eine obere Grenze für die Anzahl der Beziehungen gibt, die mit wiederholten Eigenschaften erreicht werden können . Wenn Sie viele Tausende oder mehr, viele bis viele Beziehungen benötigen oder Sie Beziehungen nennen müssen, funktioniert auch eine zwischengeordnete Entität, die zwei Schlüsseleigenschaften enthält, die jeweils auf ein Ende der Beziehung zeigen, aber im Allgemeinen weniger effizient ist und Sie möglicherweise haben um einige redundante Informationen in dieser Entität zu speichern, wenn Sie Übersichtsansichten benötigen, um zusätzliche Lookups zu vermeiden. –

Antwort

12

Nein, das nicht der richtige Weg, um darüber zu gehen.

Sie können mit nur einem wiederholten Eigenschaft eine many-to-many-Beziehung Modell:

class Person(ndb.Model): 
    guilds = ndb.KeyProperty(kind="Guild", repeated=True) 

class Guild(ndb.Model): 
    @property 
    def members(self): 
     return Person.query().filter(Person.guilds == self.key) 

    def add_person(self, person): 
     person.guilds.append(self.key) 
     person.put() 

oder umgekehrt mit:

class Person(ndb.Model): 
    @property 
    def guilds(self): 
     return Guild.query().filter(Guild.members == self.key) 

class Guild(ndb.Model): 
    members = ndb.KeyProperty(kind="Person", repeated=True) 

    def add_person(self, person): 
     self.members.append(person.key) 
     self.put() 

Die Richtung der Beziehung von vielen Faktoren abhängt (Ihr Unternehmen Modell, Anzahl der Gilden pro Person, Anzahl der Mitglieder pro Gilde, etc.)

+0

Das hat super funktioniert, danke. Immer noch nicht sicher, warum ich das bekam: 'TypeError: 'KeyProperty' Objekt ist nicht iterable ' mit der gleichen Art von Eigenschaft. Das funktioniert für mich, aber ich denke, dass die Obergrenze für eine wiederholte KeyProperty 5000 ist, also könnte es für Leute mit mehr Entitäten nicht so gut sein. – chrisw

+0

Gern geschehen. Wenn Sie auf jeder Seite der Beziehung viele Entitäten haben, sollten Sie möglicherweise eine andere Entität für die Beziehung erstellen, genauso wie Sie eine neue Tabelle in relationaler Datenbank für Viele-zu-Viele-Beziehungen erstellen. Denken Sie jedoch daran, dass Sie keine Joins bei Datenspeicherabfragen durchführen können. –

+0

Das sollten Sie vermeiden. beziehen Sie sich auf diese http://stackoverflow.com/questions/15377119/gae-ndb-design-performance-and-use-of-repeated-properties/15418435#15418435 – EsseTi