morpheus
morpheus

Reputation: 20382

Google App Engine: Datastore Query in which the WHERE clause points to a Reference Property

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

Answers (2)

Daniel Roseman
Daniel Roseman

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

Roman Levin
Roman Levin

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

Related Questions