I think I\'m overlooking something simple here, I can\'t imagine this is impossible to do.
I want to filter by a datetime attribute and then order the result by a rankin
The Datastore has some limitations on queries. One is not allowing to combine inequality filter on one property with order on anther property. You can find more restrictions here:
https://cloud.google.com/appengine/docs/python/ndb/queries
I don't know since when, but current SDK may return subtle different error:
BadArgumentError: First ordering property must be the same as inequality filter property, if specified for this query; received ranking, expected submitted
In my case, I could work around the error with this:
query.filter("submitted >=" thisweek).order("submitted").order("ranking")
Edited 2013-02-08: As Horselover Fat mentioned in a comment, it only avoids an error.
I used another trick, which worked out simply because of the format I needed my data in (a list of dicts). In this case I run the datetime-based query, create dicts from the returned ents, and then sort by the numeric 'counter' property. Reversing the sort gave me a descending order. Keep in mind I only requested 10 results, on a fairly small datastore.
q = food.Food.all()
q.filter("last_modified <=", now)
q.filter("last_modified >=", hour_ago)
ents = q.fetch(10)
if ents:
results = [{
"name": ent.name,
"counter": ent.counter
} for ent in ents]
# reverse list for 'descending' order
results.sort(reverse=True)
Example result:
[{'counter': 111L, 'name': u'wasabi'}, {'counter': 51L, 'name': u'honeydew'}, {'counter': 43L, 'name': u'mars bar'}, {'counter': 37L, 'name': u'scallop'}, {'counter': 33L, 'name': u'turnip'}, {'counter': 29L, 'name': u'cornbread'}, {'counter': 16L, 'name': u'mackerel'}, {'counter': 10L, 'name': u'instant coffee'}, {'counter': 3L, 'name': u'brussel sprouts'}, {'counter': 2L, 'name': u'anchovies'}]
The datastore isn't capable of ordering a query that contains an inequality by any property other than the one used in the inequality.
This can often be worked around by adding a property that can be filtered with an equality; in this case, it may be possible to have a BooleanProperty tracking whether an entity is from the current week, and update it for all entities at the end of each week.
The simplest way would be to split your query:
q1 = query.filter("submitted >=" thisweek)
q2 = q1.order("ranking")