GAE:高效查询实体及其引用的实体

GAE: Efficiently querying entities and their referenced entities

我正在尝试有效地 return 实体列表,以及它们在模板视图中各自引用的实体。例如

我们正在处理两种类型:

class Event(ndb.Model):
    """An fun activity or event"""
    name = ndb.StringProperty()
    venue = ndb.KeyProperty()

class Venue(ndb.Model):
    """The venue of an event"""
    name = ndb.StringProperty()
    address = StringProperty()

Event 种类通过 ndb.KeyProperty() 引用 Venue。要将事件列表及其各自的场地显示到模板中,我可以先执行此查询:

# we can fetch this from memcache
events = Event.query().fetch()

那么,在我看来:

{% for event in events %}
    Event Name: {{event.name}}
    Event Venue: {{event.venue.get().name}}  # is this line costly?
{% endfor %}

使用这种方法,我认为对于每个事件,都会对其各自的场地进行 get() 调用。如果这是真的,这听起来很昂贵。假设有 100 个事件。每个页面加载将产生 100 event.venue.get().name 个请求。这意味着每天 10000 次适度的页面浏览量会产生 10000 * 100 .get() 请求。这听起来正确吗?

这是解决这个问题的最佳方法吗?如果没有,我可以考虑哪些选择?

首先,根据数据集中场所的总数,它们可能都很容易放入 Memcache 中。因此,除非修改场地,否则您可以连续几天不接触数据存储 - 无论页面浏览量如何。确保您也将 Memcache 用于您的场所。

其次,一种更有效的检索实体的方法是在批处理请求中。遍历您的事件,创建您需要的所有场所的列表(顺便说一下,如果多个事件发生在同一场所,则该列表可能小于事件数量 - 我没有在您的代码中看到该检查),然后为所有场馆发出批量请求。

这是获取所有场地名称的 Python 代码:

venue_keys = set(event.venue for event in events)
venues = ndb.get_multi(venue_keys)
venue_name = {venue.key, venue.name for venue in venues}

然后,在您的模板中,您可以使用:

Event Venue: {{ venue_name.get(event.venue, 'No venue') }}