I have the following objects:
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)
And now to optimize the performance of my queries, I want to build a query that will return all the contacts including only the properties name & addresses.
So I built a projection query like this:
qry = Contact.query(projection=['name', 'addresses'])
Which triggers this error:
InvalidPropertyError: Structured property addresses requires a subproperty
Any idea how to make a projection query that includes structured properties?
That query is not possible. Unfortunately the exception isn't very clear, but the issue is the result of how sub-properties are actually stored. ndb explodes your
StructuredProperty
so that each value is included separately. So, for example, the entity:This will get expanded to an entity with properties:
When datastore indexes this, you'll end up with the following in your index (in the EntitiesByProperty index, to be specific):
Projection queries work by doing an index scan without looking up the actual entity. In this case, each index row does not have enough information to populate the entire address.
tldr; You can't project a
StructuredProperty
.