Selecting Child Entities with GQL Queries

In Google App Engine, you can create owned one-to-many relationships between entities. The classic example you were taught at uni is that a Book owns a Chapter, which in turn, owns a Paragraph. For my site, stolencamerafinder, the example is that a camera Make owns a set of Models.

If you want to query for the model directly in GQL (from the app engine dashboard for example) you can create the key by specifying the full parent chain:

SELECT * FROM Model where __key__ = KEY('Make', 'canon', 'Model', 'canon eos 5d')

Google’s GQL reference was a little sparse on this syntax so I’m posting it here in the hope you find this faster than I worked it out.

For completeness, this is the difference it makes in JDO. My old code looked something like this:

PersistenceManager pm = PMF.get().getPersistenceManager();
Key makeKey = KeyFactory.createKey(Make.class.getSimpleName(), makeName);
Make make = pm.getObjectById(Make.class, key);
List<Model> models = make.getModels();

for (Model model : models) {
    if (model.getName().equals(modelName)) {
        return model;
    }
}

It doesn’t take much imagination to realise this doesn’t scale very nicely as the number of models increases. The new code looks like this:

PersistenceManager pm = PMF.get().getPersistenceManager();
Key makeKey = KeyFactory.createKey(Make.class.getSimpleName(), makeName);
// Can create the Model key by specifying parent key...
Key modelKey = KeyFactory.createKey(makeKey, Model.class.getSimpleName(), name);
// Bam! Get the child entity in a single query
Model model = pm.getObjectById(Model.class, modelKey);

I wouldn’t have noticed this performance bottle neck if it wasn’t for appwrench. It looks a little dead to be honest, but works well.

2 thoughts on “Selecting Child Entities with GQL Queries”

  1. You’re right. I don’t recall really struggling to choose the name “Make” it just seemed like the only option at the time, probably because in EXIF data it is called Make and Model.

    Now that I look at it, “makeKey” is a pretty stupid variable name, I just never read it in my head in the way you’re reading it.

    The “Make” object is mapped to my persistence object so refactoring it is more of a pain than I’d like. Since I’m the only person working on it, it’s not a priority to change it but you make a valid point.

    As for your link, I agree with most of the points but I completely disagree with the last bullet about lower case Ls and upper case Os. I’ve never found it a problem and am struggling to contrive one. Sure, avoid them if there is an equally good name that doesn’t use them, but don’t pick a worse name so as not to break that rule.

Leave a Reply

Your email address will not be published. Required fields are marked *