Gianluca Bargelli Gianluca Bargelli - 1 month ago 17
Python Question

GQL: Not equal filter on a multivalued property

Tinkering a little with GAE's datastore i've found that i can't think a proper way to filter out results using the inequality filter '!=' on a multivalued property:

class Entry(db.Model):
...
tags = db.StringListProperty()

e1 = Entry()
e2 = Entry()
e1.tags = ['tag1', 'tag2', 'tag3']
e2.tags = ['tag1', 'tag3', 'tag4']

# I want to exclude all the results containing 'tag2'
db.GqlQuery("""SELECT * FROM Entry
WHERE tags != 'tag2' """)


The problem is that this query returns both e1 and e2 but i want only e2.

I think that this happens because the inequality filter evaluates as ANY (TRUE if at least one value is != 'tag2'. There's a way to apply the filter to ALL? (TRUE if all the values are != 'tag2')?

I know that GAE's Datastore is not relational but i'd like to know how to cleverly solve/think this kind of queries.

Thanks ;)

Answer

I've thought about this a bunch and I don't think there is a good way to do it (please correct me if I'm wrong). My non-clever solution is to not use StringListProperty and to cascade a bunch of filters:

class Entry(db.Model):
  ...
  tag_1 = db.StringProperty();
  tag_2 = db.StringProperty();
  ...
Entry.all().filter('tag_1 !=', tag).filter('tag_2 !=', tag) ...

I'm not going to begin to describe the obvious problems with this solution, but at least it does what you want.