我有以下对象:
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:结构化属性地址需要子属性
知道如何制作包含结构化属性的投影查询吗?
答案 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'])
但是,由于重复,您将获得与地址的每个变体重复的联系人 - 您必须手动组合它们。您可以在有关投影查询的文档中阅读更多内容。