在App Engine中使用get_by_key_name获取子实体列表(Python)

2 投票
2 回答
1339 浏览
提问于 2025-04-15 15:18

我在使用实体组的过程中遇到了一些小麻烦,刚开始的时候有点尴尬(可以看看这个链接:在某些情况下,App Engine 的 get_by_key_name 调用使用现有的 key_name 返回 None)。

现在我发现,对于有多个父实体的子实体,我不能对实体列表进行正常的 get_by_key_name 调用。正如模型文档所说,

一次请求多个实体(通过 get_by_key_name 调用)时,所有实体必须有相同的父实体。

我已经习惯做类似下面的事情:

# 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

现在,ContentModel 实体是 Model 实体的子实体,这样做就不行了,因为有单一父实体的限制。

一个简单的方法来解决这个问题,就是能够在 get_by_key_name 调用中传递一个父实体的列表,但我猜这背后一定有个好理由,说明现在不允许这样做。我在想,这是不是一个硬性规定(也就是说绝对不可能实现这样的调用),还是说数据库模块可以修改,让这种调用可以工作,即使这样会增加 CPU 的开销。

我也很想看看其他人是怎么完成这种任务的。我能想到很多处理方法,比如使用 GQL 查询,但我想不出哪种方法能达到 get_by_key_name 调用的性能。

2 个回答

1

我很不好意思地说,这个限制(“必须在同一个实体组中”)其实在这种情况下已经不再适用了。如果你觉得有必要,欢迎去提交一个文档错误

无论如何,get_by_key_name其实只是get的一个更好看的写法,正如Bill Katz所示。你甚至可以更进一步,使用db.get来处理一组键,这样就能一次性获取所有内容——db.get对模型类型并不在意。

4

只需要创建一个键的列表,然后对它进行获取操作。

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)

需要注意的是,我假设每个内容模型(ContentModel)实体的键名(key_name)和它的父模型(Model)是一样的。对于一对一的关系,使用相同的键名是合理的。

撰写回答