Snowman
Snowman

Reputation: 32071

Doing an ancestor query with nested AND/OR in Google App Engine

I'm using Google App Engine NDB, and trying to do the following query:

query = Club.query(ndb.OR(
ndb.AND(Club.memberIds == userId, Club.modifiedDate > date), 
ndb.AND(Club.activityDate > date, ancestor = userKey)
))

However, I get a run time error:

TypeError: __new__() got an unexpected keyword argument 'ancestor'

It has something to do with the position of ancestor. This answer was able to point out the solution in one case, but that solution would not apply here, since the ancestor is in the actual AND clause.

  1. How can I reformat this query to work?
  2. Is this query a bad idea? Is it too complex? Will it cost me any additional reads than usual due to its complexity?

Upvotes: 1

Views: 533

Answers (2)

Guido van Rossum
Guido van Rossum

Reputation: 16890

You cannot use the ancestor as part of a filter; it must be a keyword parameter directly on the query() call. Currently, OR queries are turned into multiple queries anyway, so the only benefit the OR() method gives you is easier combining of the results. But for that to work you have to order by key anyway, and it's trivial to write a little merge function that merges two sets of query results ordered by key. (It's also possible to have that done by invoking ndb.query._MultiQuery() but the latter is not a documented API and is rather iffy to get right, so it's probably better to do this yourself.)

Upvotes: 1

Hans Then
Hans Then

Reputation: 11322

Is it possible to rewrite the query to use GQL?

EDIT

To shoot down my own suggestion. It is not possible to rewrite your query to use GQL. GQL does not support OR.

See: https://developers.google.com/appengine/docs/python/datastore/gqlreference

SUGGESTION You can do the query you want if you also modify the ancestor object as a Model attribute. E.g.

class Club(ndb.Model):
    parent = ndb.KeyProperty()

Upvotes: 1

Related Questions