App Engine - 带有投影的 NDB 查询需要子属性?

App Engine - NDB query with projection requires subproperty?

我有以下对象:

class Address(ndb.Model):
  type = ndb.StringProperty() # E.g., 'home', 'work'
  street = ndb.StringProperty()
  city = ndb.StringProperty()

class Friend(ndb.Model):
  first_name = ndb.StringProperty() # E.g., 'home', 'work'
  last_name = ndb.StringProperty()

class Contact(ndb.Model):
  name = ndb.StringProperty()
  addresses = ndb.StructuredProperty(Address, repeated=True)
  friends = ndb.StructuredProperty(Friend, repeated=True)

现在为了优化我的查询性能,我想构建一个查询,该查询将 return 所有联系人,仅包括属性名称和地址。

所以我构建了一个这样的投影查询:

qry = Contact.query(projection=['name', 'addresses'])

触发此错误的原因:

InvalidPropertyError: Structured property addresses requires a subproperty

知道如何进行包含结构化属性的投影查询吗?

无法查询。不幸的是,异常不是很清楚,但问题是子属性实际存储方式的结果。 ndb 展开你的 StructuredProperty 以便每个值都单独包含。因此,例如,实体:

Contact(name="Bob", addresses=[
    Address(type="Work", city="San Francisco"),
    Address(type="Home", city="New York")])

这将扩展为具有属性的实体:

name = "Bob"
addresses.type = ["Work", "Home"]
addresses.city = ["San Francisco", "New York"]

当数据存储对此进行索引时,您最终会在索引中得到以下内容(在 EntitiesByProperty index 中):

"addresses.city" "New York"      Key(Contact, <id>)
"addresses.city" "San Francisco" Key(Contact, <id>)
"addresses.type" "Home"          Key(Contact, <id>)
"addresses.type" "Work"          Key(Contact, <id>)
"name"           "Bob"           Key(Contact, <id>)

投影查询通过在不查找实际实体的情况下进行索引扫描来工作。在这种情况下,每个索引行没有足够的信息来填充整个地址。

tldr;你不能投影 StructuredProperty.

将结构化 属性 视为属性列表并请求每个属性:

Contact.query(projection=['name', 'addresses.type', 'addresses.street', 'addresses.city'])

但由于它是重复的,您将获得地址的每个变体的重复联系人 -- 您必须手动组合它们。您可以在有关投影查询的文档中阅读更多内容。