Google app engine 应用程序引擎-带投影的NDB查询是否需要子属性?

Google app engine 应用程序引擎-带投影的NDB查询是否需要子属性?,google-app-engine,google-cloud-datastore,app-engine-ndb,google-app-engine-python,Google App Engine,Google Cloud Datastore,App Engine Ndb,Google App Engine Python,我有以下目标: 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 = nd

我有以下目标:

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)
现在,为了优化查询的性能,我想构建一个查询,该查询将返回所有联系人,仅包括属性名称和地址

因此,我构建了一个投影查询,如下所示:

qry = Contact.query(projection=['name', 'addresses'])
触发此错误的原因:

InvalidPropertyError:结构化属性地址需要子属性


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

该查询是不可能的。不幸的是,这个异常并不十分清楚,但问题是子属性实际上是如何存储的。ndb分解您的
结构属性
,以便分别包含每个值。因此,例如,实体:

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"]
当数据存储对此进行索引时,索引中将包含以下内容(具体而言,在中):

“地址.城市”“纽约”键(联系人,)
“地址.城市”“旧金山”密钥(联系人,)
地址。键入“主页”键(联系人)
地址。键入“工作”键(联系人)
姓名“Bob”键(联系人,)
投影查询通过执行索引扫描而不查找实际实体来工作。在这种情况下,每个索引行没有足够的信息填充整个地址


tldr;您不能投影
结构化属性

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

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

但是,由于它是重复的,你会得到重复的联系人与地址的每一个变化-你必须手动组合他们。您可以在文档中阅读有关投影查询的更多信息。

这是正确答案:您可以投影StructuredProperty,但必须请求每个子属性
Contact.query(projection=['name', 'addresses.type', 'addresses.street', 'addresses.city'])