Nate Anderson
Nate Anderson

Reputation: 21094

ANCESTOR Query Parse Error: Using DISTINCT

Not this question (where the problem is using ANCESTOR = instead of ANCESTOR IS)

I used ANCESTOR IS properly:

SELECT DISTINCT batch_no 
FROM Entry 
WHERE ANCESTOR IS KEY('ag1kZXZ-dHRiLXRhbWVychkLEgdCcmV3ZXJ5IgxCUi1USEVSRURQRUEM')

But I still got an error:

Identifier is a reserved keyword as symbol ANCESTOR

a screenshot of Google interactive GQL console followed by the error "Identifier is a reserved keyword as symbol ANCESTOR"

Why is that?

EDIT

I'm getting the same error later years later as I try to update from db to ndb, but I think it's a different reason...

Identifier is a reserved keyword at symbol ANCESTOR

But in this case my query is not using DISTINCT

SELECT *
FROM Balance
WHERE ANCESTOR IS KEY('...')
AND first_balance_ever = TRUE
ORDER BY created_date

So I'm not sure the problem here, maybe it's ANCESTOR related, maybe it's KEY(...) related...

Upvotes: 2

Views: 102

Answers (2)

Nate Anderson
Nate Anderson

Reputation: 21094

I modified my question because I faced this error years later when updating from db to ndb.

If only going from db to ndb My problem was a GQL Query like this

"ANCESTOR IS KEY('{}')".format(model.key)

Notice the difference was going

  • from this: model.key(), which returned a "url safe" encodable string value...
  • to model.key, which stringifies as KEY('Kind', 'id')

The result was a this string, which is clearly wrong:

ANCESTOR IS KEY('KEY('Kind', 'id')')

If going from db or ndb to the Datastore

I think the problem is described here, and documented here

Python GQL expression ANCESTOR IS <entity-or-key-value> is represented in Datastore GQL as the more general expression __key__ HAS ANCESTOR <key-value>

So I think db is using Python GQL, whereas ndb might be using Datastore GQL.

Note also:

Python GQL supports queries using a URL-safe (base64-encoded) key. Datastore GQL does not.

...although note that ndb does have this method...

key = ndb.Key(urlsafe=encoded_key)

The "DB to NDB Client Library Migration" documentation doesn't make it clear how GQL changes... although does imply ndb keys are different than db keys:

You can even convert between ext.db and NDB keys using ndb.Key.from_old_key() and key.to_old_key().

The legacy GQL reference says the Key can be:

an entity key literal, with either a string-encoded key or a complete path of kinds and key names/IDs:

  • KEY('encoded key')
  • KEY('kind', 'name'/ID [, 'kind', 'name'/ID...])

But the Datastore GQL reference says

Upvotes: 0

Nate Anderson
Nate Anderson

Reputation: 21094

In this case, DISTINCT was causing the problem. Remove it and the query works as expected.

I think the query is implicitly projecting only that property you DISTINCT on, so you cannot access the key/ancestor for ANCESTOR IS. (But is this true even if you use SELECT *?)

But the error message is not very clear...

Google describes that DISTINCT is experimental. Mentions this in db.Query documentation:

Grouping(experimental)

Projection queries can use the distinct keyword to ensure that only completely unique results will be returned in a result set. This will only return the first result for entities which have the same values for the properties that are being projected.

And in the GQL documentation

The optional DISTINCT(experimental) clause specifies that only completely unique results will be returned in a result set. This will only return the first result for entities which have the same values for the properties that are being projected.

Upvotes: 2

Related Questions