Lipis
Lipis

Reputation: 21835

How can I filter by key, or keys, a query in Python for Google App Engine?

I have a query and I can apply filters on them without any problem. This works fine:

query.filter('foo =', 'bar')

But what if I want to filter my query by key or a list of keys?

I have them as Key() property or as a string and by trying something like this, it didn't work:

query.filter('key =', 'some_key')        #no success
query.filter('key IN', ['key1', 'key2']) #no success

Upvotes: 3

Views: 4679

Answers (4)

mattes
mattes

Reputation: 9429

Have a look at: https://developers.google.com/appengine/docs/python/ndb/entities?hl=de#multiple

list_of_entities = ndb.get_multi(list_of_keys)

Upvotes: 0

Luke Francl
Luke Francl

Reputation: 31474

You cannot filter on a Key. Oops, I was wrong about that. You can filter on a key and other properties at the same time if you have an index set up to handle it. It would look like this:

key = db.Key.from_path('MyModel', 'keyname')
MyModel.all().filter("__key__ =", key).filter('foo = ', 'bar')

You can also look up a number of models by their keys, key IDs, or key names with the get family of methods.

# if you have the key already, or can construct it from its path
models = MyModel.get(Key.from_path(...), ...)

# if you have keys with names
models = MyModel.get_by_key_name('asdf', 'xyz', ...)

# if you have keys with IDs
models = MyModel.get_by_id(123, 456, ...)

You can fetch many entities this way. I don't know the exact limit. If any of the keys doesn't exist, you'll get a None in the list for that entity.

If you need to filter on some property as well as the key, you'll have to do that in two steps. Either fetch by the keys and check for the property, or query on the property and validate the keys.

Here's an example of filtering after fetching. Note that you don't use the Query class's filter method. Instead just filter the list.

models = MyModels.get_by_key_name('asdf', ...)

filtered = itertools.ifilter(lambda x: x.foo == 'bar', models)

Upvotes: 1

Nick Johnson
Nick Johnson

Reputation: 101149

Whilst it's possible to filter on key - see @dplouffe's answer - it's not a good idea. 'IN' clauses execute one query for each item in the clause, so you end up doing as many queries as there are keys, which is a particularly inefficient way to achieve your goal.

Instead, use a batch fetch operation, as @Luke documents, then filter any elements you don't want out of the list in your code.

Upvotes: 3

dplouffe
dplouffe

Reputation: 565

You can filter queries by doing a GQL Query like this:


result = db.GqlQuery('select * from Model where __key__ IN :1', [db.Key.from_path('Model', 'Key1'), db.Key.from_path('Model', 'Key2')]).fetch(2)

or


result = Model.get([db.Key.from_path('Model', 'Key1'), db.Key.from_path('ProModelduct', 'Key2')])

Upvotes: 1

Related Questions