views:

437

answers:

1

If I have two tables, Customers and Orders, and I want to look up the latest order for a customer, how would I do this on Google App Engine using GQL?

Normally, I would join these two tables through the foreign key, customer_id, which exists in the orders table.

select orders.* from customers, orders 
where customers.customer_id = orders.customer_id
and orders.order_id = (select top 1 sub_orders.order_id from orders sub_orders 
                where sub_orders.customer_id = orders.customer_id 
                order by sub_orders.order_date desc)

However, since joins do not seem to be possible on Google App Engine, I'm not sure how to work around this limitation. Any suggestions would be appreciated.

+7  A: 

The DataStore in Google App Engine is really quite different from a relational database. There are some similarities, but it's important to understand the differences when you design you data model.

The way you would normally define this kind of relationship is by using reference properties:

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

class Order(db.Model):
   customer = db.ReferenceProperty( Customer,
                                    collection_name = 'orders' )

The ReferenceProperty in the Order entity definition results in the creation of a property in the Customer entity, named 'orders', so that if 'customer' is a Customer instance, you can find all the orders by referring to 'customer.orders'.

For example:

customer = Customer.gql("WHERE name = :1", "Bob")[0] # Returns the first customer named Bob
order1 = customer.orders[0]
order2 = customer.orders.order("date")[0] # Sorts the Orders by date and gets the first one

Reference properties are documented here.

Another important concept to understand is the idea of Entity Groups. Entities in an Entity Groups are stored on the same node, and therefore they can be stored and retrieved more efficiently. They're also crucial for using transactions.

Ori Pessach
Wow! This is awesome! Thanks, man.
pez_dispenser
order2 = customer.orders.order("date")[0] ---- Regarding the order method you called here on the orders object, what's the best place to find all of the available options for that method? For example, I'm wondering if I could say order("date asc") or order("date desc") and it will translate that into the corresponding GQL? – fraggle 1 sec ago
pez_dispenser
As far as Entity Groups go, what would be the equivalent (if any) in the relational world? I'm not sure I get what you mean about "stored on the same node".
pez_dispenser
Regarding Entity Groups: The Google data store is a distributed database. App Engine's API's are designed to let you take advantage of that to scale your application when you end up storing a lot of data. Data is not guaranteed to be stored on the same machine - Entity Groups let you define, in essence, that certain items of data go together and should be stored together. For example, you could make the customer and the customer's orders an entity group. Another customer and his orders would belong to another group, and might be stored on a different machine.
Ori Pessach
I'm not sure what a SQL equivalent would be - maybe shards? The concept doesn't really map well to relational databases, as far as I know.Google's documentation has a lot of information about sorting options. I'm not that familiar with the various options, so you might want to consult the documentation.
Ori Pessach
@pez_dispenser: The collection properties ('orders', etc) are Query objects. Query objects implement a programmatic interface to querying the datastore that is just as capable as GQL. Both GQL and Queries translate into the same lower level code. For docs, see http://code.google.com/appengine/docs/python/datastore/queryclass.html and related pages.
Nick Johnson