Reputation: 20382
In my datastore I have an entity Book
that has reference to Owner
that has reference to ContactInfo
which has a property zipcode
on it. I want to query for all books within a certain zipcode. How can I do this? I understand I can't write a query where I can do:
q = db.Query(Book).filter('owner.contact_info.zipcode =', 12345)
Upvotes: 0
Views: 279
Reputation: 599956
This is exactly the sort of thing you cannot do with the App Engine datastore. It is not a relational database, and you cannot query it as one. One of the things this implies is that it does not support JOINs, and you cannot do queries across entity types.
Because of this, it is usually not a good idea to follow the full normalized form in creating your data models. Unless you have a very good reason for keeping them separate, ContactInfo should almost certainly be merged with Owner. You might also want to define a repeated ReferenceProperty on Owner that records books_owned
: then you can do a simple query and some gets to get all the books:
owners = db.Query(Owner).filter('zipcode', 12345)
books = []
for owner in owners:
book_ids.extend(owner.books_owned)
books = db.get(book_ids)
Edit the field would look like this:
class Owner(db.Model):
...
books_owned = db.ListProperty(db.Key)
If you update the schema, nothing happens to the existing entities: you will need to go through them (perhaps using the remote API) and update them to add the new data. Note though that you can just set the properties directly, there's no database migration to be done.
Upvotes: 2
Reputation: 471
If contact info is a separate model, you will first need to find all ContactInfo
entities with zipcode == 12345
, then find all of the Owner
entities that reference those ContactInfo
entities, then find all the Book
entities that reference those Owner
entities.
If you're still able to change your model definitions at all, it would probably be wise to denormalize at least ContactInfo
in the Owner
model, and possibly also the Owner
inside each Book
.
Upvotes: 0