views:

498

answers:

2

My adventures with entity groups continue after a slightly embarrassing beginning (see Under some circumstances an App Engine get_by_key_name call using an existing key_name returns None).

I now see that I can't do a normal get_by_key_name call over a list of entities for child entities that have more than one parent entity. As the Model docs say,

Multiple entities requested by one (get_by_key_name) call must all have the same parent.

I've gotten into the habit of doing something like the following:

# Model just has the basic properties
entities = Model.get_by_key_name(key_names)
# ContentModel has all the text and blob properties for Model
content_entities = ContentModel.get_by_key_name(content_key_names)

for entity, content_entity in zip(entities, content_entities):
 # do some stuff

Now that ContentModel entities are children of Model entities, this won't work because of the single-parent requirement.

An easy way to enable the above scenario with entity groups is to be able to pass a list of parents to a get_by_key_name call, but I'm guessing that there's a good reason why this isn't currently possible. I'm wondering if this is a hard rule (as in there is absolutely no way such a call could ever work) or if perhaps the db module could be modified so that this type of call would work, even if it meant a greater CPU expense.

I'd also really like to see how others accomplish this sort of task. I can think of a bunch of ways of handling it, like using GQL queries, but none I can think of approach the performance of a get_by_key_name call.

+3  A: 

Just create a key list and do a get on it.

entities = Model.get_by_key_name(key_names)
content_keys = [db.Key.from_path('Model', name, 'ContentModel', name) 
                for name in key_names]
content_entities = ContentModel.get(content_keys)

Note that I assume the key_name for each ContentModel entity is the same as its parent Model. (For a 1:1 relationship, it makes sense to reuse the key_name.)

Bill Katz
Great idea. I don't make use of db.Key.from_path nearly enough.
jamtoday
+1  A: 

I'm embarrassed to say that the restriction ('must be in the same entity group') actually no longer applies in this case. Please do feel free to file a documentation bug!

In any case, get_by_key_name is only syntactic sugar for get, as Bill Katz illustrates. You can go a step further, even, and use db.get on a list of keys to get everything in one go - db.get doesn't care about model type.

Nick Johnson
If you're getting more than one child entity and attempt to pass a list for parent, it returns a BadArgumentError since it won't accept a list of keys. So unless you can pass a list of parent keys, it seems like the restriction is still in place.
jamtoday
A list for parent? No, that obviously won't work - you need to construct key objects and use db.get() on them. I wasn't aware you were attempting to get child entities.
Nick Johnson