2014-06-24 15 views
8

Provare a modellare una relazione molti-a-molti con ndb. Qualcuno può indicare un buon esempio di come farlo?Relazione molti-a-molti in ndb

A qui è un esempio di ciò che ho in questo momento:

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() 

È questo il modo corretto di andare su di esso? Ho dato una buona occhiata in giro ma non riesco a trovare alcuna buona documentazione sull'argomento.

Nel visualizzatore del datastore, posso vedere questa relazione memorizzata come un elenco di chiavi, che mi aspetto.

Tuttavia, quando cerco di usarle nei metodi della classe Persona come questo:

for guild in self.guilds: 

ottengo:

TypeError: 'KeyProperty' object is not iterable 
+0

'per la gilda in self.guilds' dovrebbe funzionare. Controlla se hai messo 'repeat = True' in Person:' guilds = ndb.KeyProperty (kind = "Guild", ripetuto = True) ' –

+0

Nota c'è un limite superiore al numero di relazioni che possono essere raggiunte con proprietà ripetute . Se hai bisogno di molte migliaia o più, molte o molte relazioni, o hai bisogno di nominare le tue relazioni, allora anche un'entità intermedia che detiene due proprietà chiave ciascuna che punta a ciascuna estremità della relazione funzionerà, ma in genere è meno efficiente e potresti avere per memorizzare alcune informazioni ridondanti in questa entità se sono necessarie viste riepilogative per evitare looklup aggiuntivi. –

risposta

12

No. Questo non è il modo corretto di procedere.

È possibile modellare una relazione molti-a-molti con una sola proprietà ripetuto:

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() 

o viceversa con:

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() 

La direzione della relazione dipende da molti fattori (il vostro business modello, numero di gilde per persona, numero di membri per gilda, ecc.)

+0

Questo ha funzionato molto bene. Ancora non sono sicuro del motivo per cui ho ricevuto il messaggio: 'TypeError: 'Oggetto KeyProperty' non è iterable' con lo stesso tipo di proprietà. Questo funziona per me ma penso che il limite superiore su una KeyProperty ripetuta sia 5000, quindi potrebbe non essere buono per le persone con più entità. – chrisw

+0

Prego. Se ci sono molte entità su ciascun lato della relazione, forse dovresti creare un'altra entità per la relazione, nello stesso modo in cui crei una nuova tabella nel DB relazionale per le relazioni molti-a-molti. Ma ricorda che non puoi fare join su query datastore. –

+0

Questo è qualcosa che dovresti evitare. fai riferimento a questo http://stackoverflow.com/questions/15377119/gae-ndb-design-performance-and-use-of-repeated-properties/15418435#15418435 – EsseTi

Problemi correlati