Search code examples
google-app-enginegoogle-cloud-datastoreapp-engine-ndbendpoints-proto-datastore

Combining results of multiple ndb inequality queries


The NDB Datastore forbids multiple inequality queries on different properties. To get around this, I thought that the solution might be to combine the results of multiple independent queries. I found this 2011 question which recommends geohashing, with which I am not familiar. So, perhaps there is a better solution today.

Consider these two queries:

q1 = User.query(User.age < 18).fetch()
q2 = User.query(User.city != 'New York City').fetch()

I attempt to join them like this:

results = set(q1).intersection(q2)

However, I encounter TypeError: Model is not immutable.

My questions:

  • Is there a better way to deal with multiple inequality filters on different properties?
  • If not, how can I resolve the TypeError above?

Thank you for the assistance.


Solution

  • If you can restructure your User model, you could put in some more properties to make the queries simpler. For example, if you query on the same age ranges, then make a property that encodes the ranges:

    age_range = ndb.IntegerProperty()    # 0 = 0-17, 1 = 18-29, 2 = 30-39, etc.
    

    Then you can have:

    q1 = User.query(User.age_range == 0).query(User.city != 'New York City').fetch()
    

    If your data set is small enough, you can use @TimHoffman's approach:

    q1 = User.query(User.age < 18).fetch(keys_only=True)
    q2 = User.query(User.city != 'New York City').fetch(keys_only=True)
    results = ndb.get_multi(set(q1).intersection(q2))
    

    A more heavyweight approach, that will scale up to big data sets, is the MapReduce library. You can put in multiple filters to reduce your data set.