Search code examples
pythongoogle-app-enginemany-to-manyapp-engine-ndb

Many-To-Many Relationship in ndb


Trying to model a many-to-many relationship with ndb. Can anyone point to a good example of how to do this?

At here is an example of what I have at the moment:

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

Is this the correct way to go about it? I have had a good look around but can't seem to find any good documentation on the subject.

In the datastore viewer, I can see this relationship being stored as a list of Keys, which I expect.

However, when I try to use them in the Person class methods like this:

for guild in self.guilds:

I get:

TypeError: 'KeyProperty' object is not iterable

Solution

  • No. That is not the correct way to go about it.

    You can model a many-to-many relationship with only one repeated property:

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

    or viceversa with:

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

    The direction of the relationship depends on many factors (your business model, number of guilds per person, number of members per guild, etc.)