Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing related object key without fetching object in App Engine

In general, it's better to do a single query vs. many queries for a given object. Let's say I have a bunch of 'son' objects each with a 'father'. I get all the 'son' objects:

sons = Son.all()

Then, I'd like to get all the fathers for that group of sons. I do:

father_keys = {}
for son in sons:
    father_keys.setdefault(son.father.key(), None)

Then I can do:

fathers = Father.get(father_keys.keys())

Now, this assumes that son.father.key() doesn't actually go fetch the object. Am I wrong on this? I have a bunch of code that assumes the object.related_object.key() doesn't actually fetch related_object from the datastore.

Am I doing this right?

like image 693
sotangochips Avatar asked Jan 16 '10 02:01

sotangochips


2 Answers

You can find the answer by studying the sources of appengine.ext.db in your download of the App Engine SDK sources -- and the answer is, no, there's no special-casing as you require: the __get__ method (line 2887 in the sources for the 1.3.0 SDK) of the ReferenceProperty descriptor gets invoked before knowing if .key() or anything else will later be invoked on the result, so it just doesn't get a chance to do the optimization you'd like.

However, see line 2929: method get_value_for_datastore does do exactly what you want!

Specifically, instead of son.father.key(), use Son.father.get_value_for_datastore(son) and you should be much happier as a result;-).

like image 170
Alex Martelli Avatar answered Oct 20 '22 01:10

Alex Martelli


I'd rather loop through the sons and get parent's keys using son.parent_key().

parent_key()

Returns the Key of the parent entity of this instance, or None if this instance does not have a parent.

Since all the path is saved in the instance's key, theoretically, there is no need to hit the database again to get the parent's key.

After that, it's possible to get all parents' instances at once using db.get().

get(keys)

Gets the entity or entities for the given key or keys, of any Model.

Arguments:

keys A Key object or a list of Key objects.

If one Key is provided, the return value is an instance of the appropriate Model class, or None if no entity exists with the given Key. If a list of Keys is provided, the return value is a corresponding list of model instances, with None values when no entity exists for a corresponding Key.

like image 28
jbochi Avatar answered Oct 20 '22 00:10

jbochi