views:

47

answers:

2

I can't seem to find a quick answer on how to get Datastore descendants given a reference to the parent entity. Here's a quick example:

# a person who has pets
john=Person(**kwargs)

# pets
fluffy=Pet(parent=john, ...)
rover=Pet(parent=john, ...)

# lengthy details about john that are accessed infrequently
facts=Details(parent=john, ...)
  1. How can I get the keys for fluffy, rover and facts using john or the key for john?
  2. With john (or key) can I get key/entity for just facts (not rover, fluffy)?
+1  A: 

You want to use an ancestor filter:

kid_keys = db.Query(keys_only=True).ancestor(john).fetch(1000)

And you can get just facts by specifying the type of facts:

facts_key = db.Query(Details, keys_only=True).ancestor(john).get()

Using get() instead of fetch() assumes that john will have only one Details child. If that is not true, call fetch to get them all.

Adam Crossland
A: 

Expanding on Adam's answer: If you don't know the key name or key ID for fluffy, rover or facts, you can't construct the keys ahead of time based just on the entity or key for john. You'll have to use ancestor queries, as in Adam's answer.

If, on the other hand, you do know the name or ID for those child entities (say, in a request handler where the ID comes in as part of the URL or something), you can construct their keys based on the john entity or its key. E.g.:

# Build a key for the parent
john_key = db.Key.from_path('Person', 1)

# Build a key for the children
fluffy_key = db.Key.from_path('Pet', 1, parent=john_key)
rover_key = db.Key.from_path('Pet', 2, parent=john_key)

# Get all three at once
john, fluffy, rover = db.get([john_key, fluffy_key, rover_key])

These examples assume that all the entity keys have IDs, but if they have names you can just substitute the string names in place of the int IDs.

Will McCutchen