Justin
Justin

Reputation: 3634

NDB: filtering by properties on multiple entities

I'm coming from a SQL background, and I'm wondering how do to filters in NDB that would be the equivalent of many joins in SQL, and how to make these queries scale. As an example:

class PromDate(ndb.Model):
  user_id = ndb.StringProperty(required=True) # user id
  age = ndb.IntegerProperty()

class DesignerBrand(ndb.Model):
  name = ndb.StringProperty()

class Socks(ndb.Model):
  owner = ndb.KeyProperty(kind=PromDate, required=True) # reference to PromDate
  designer = ndb.KeyProperty(kind=DesignerBrand, required=True) # reference to DesignerBrand
  color = ndb.StringProperty()
  do_they_smell = ndb.BooleanProperty()

class Tie(ndb.Model):
  owner = ndb.KeyProperty(kind=PromDate, required=True) # reference to PromDate
  designer = ndb.KeyProperty(kind=DesignerBrand, required=True) # reference to DesignerBrand
  color = ndb.StringProperty()

If we want to find a PromDate over 21 that owns blue Calvin Klein or Target socks that don't smell and a red tie, how do we best do this without using StructuredProperties? An example query would be extremely helpful.

What are the tradeoffs between using associations with keys like above and putting the Socks/Tie as a repeated StructuredProperty of the PromDate? Specifically, I am worried about size limitations (1MB, according to the docs) if we add tons of other clothing items (e.g., hundreds of thousands) to our PromDate.

Basically, how should we think about complex queries like this in NDB? How do we keep them fast and simple - and, most importantly, scalable at high volumes of data?

Upvotes: 0

Views: 457

Answers (2)

Rad Apdal
Rad Apdal

Reputation: 462

You can denormalize your data and form a Structured property, then run multiple filters on it.

From their samples:

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

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

def query_contact_multiple_values_in_single_sub_entity():
    query = Contact.query(Contact.addresses == Address(city='San Francisco',
                                                       street='Spear St'))
    return query

Upvotes: 1

Alex Martelli
Alex Martelli

Reputation: 881705

Unfortunately, I believe you will need several queries to whittle down the list of PromDate instances you require.

That's NoSQL for you: the more carefully you normalize your schema, the worse things can be, because, you see, no joins!

De-normalizing (with structured properties sometimes, more simply at other times -- e.g just use the designer name in lieu of a designer key so you can query on it directly) will help a bit, but, it's still a very different world from relational DBs (which is why relational DBs are still offered, e.g Google Cloud SQL, as alternatives).

Upvotes: 1

Related Questions