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

时间:2015-06-18 16:45:53

标签: 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 = 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:结构化属性地址需要子属性

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

2 个答案:

答案 0 :(得分:2)

该查询无法进行。不幸的是,异常并不是很清楚,但问题在于如何实际存储子属性。 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

答案 1 :(得分:1)

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

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

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