GAE DataStore referenceProperty relationship

2020-07-28 00:13发布

问题:

I am trying to get all parent/children from a one to many relationship. Traditionally, I could do this with a join, but doing so in the datastore is escaping me.

I have found several partial examples to do this, but not one that is complete yet.

I have:

class Owner(db.Model):
  name = db.StringProperty()

class Pet(db.Model):
  petname = db.StringProperty()
  owner = db.ReferenceProperty(Owner, collection_name='pets')

#now I want to print all pets owned by scott
scott = Owner(name="scott")
scott.put()
Pet(owner=scott,petname="rufus").put()

pets = Pet.all().filter('owner =', "scott").fetch(100)
print Pet.all().filter('owner =', "scott").fetch(0)

回答1:

Your query should work fine if you remove the quotes around "scott", I think.

You could also make all of Scott's Pet entities have his entity as their parent:

class Owner(db.Model):
    name = db.StringProperty()

class Pet(db.Model):
    petname = db.StringProperty()

scott = Owner(name="scott")
scott.put()

Pet(parent=scott, petname="rufus").put()
Pet(parent=scott, petname="fluffy").put()
Pet(parent=scott, petname="snoogums").put()

pets = Pet.all().ancestor(scott).fetch(100)
# Feed pets to your templating engine. So to speak.

By making scott the parent of the Pet entities, they are all added to the same entity group, and the ancestor query gives you a simple and stragihtforward way to get all of the Pet entities that are children of the given `Owner'. You should get much better performance with an ancestor query than a non-ancestor query.

This does impose the limitation that the Pet entities can only belong to one entity group, and if you wanted to have a Pet involved in multiple data relationships, you would have to choose another approach. If it is a one-to-one relationship, just storing a Reference to the other related entity.

To have a printable representation of your Pet entity, give it a __unicode__ method, something like this:

class Pet(db.Model):
    petname = db.StringProperty()

    def __unicode__(self):
        return "I am " + self.petname

__unicode__ should return a string with the information that you want to see printed by the print statement. As Nick wisely points out in comments, you should not use print in an AppEngine application. The SDK comes with Django templates and Jinja2. Use one of those or import one that you prefer.



回答2:

Look at The GQL examples made by google.

Use the owner name as unique key giving 'scott' to key_name instead of 'name' when instanciating Owner.

scott = Owner(key_name="scott")

Create the pet with scott as parent

pet = Pet(key_name='rufus', parent=scott)

And query his pets with

SELECT * FROM Pets WHERE ANCESTOR IS KEY('Owner', 'scott')


回答3:

You should filter by Key of Owner:

#not str "scott", use scott object.
pets = Pet.all().filter('owner =', scott).fetch(100)