Believe it or not, this is working as intended. I'll admit that I had to do a double-take myself, because the explanation for why this is happening is not necessarily obvious. The docs that describe queries are here:
http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html What you're seeing is the combination of two rules about GQL that, when combined, are causing the semi-unintuitive output you are seeing. The first rule: Rule 1: First, if a query has multiple filters on a given property, an entity will only match the query if it has an individual value for that property that matches *all* of the filters. For example, if an entity has the values [1, 2] for property x, it will not match the query WHERE x > 1 AND x < 2. Each filter does match one of x's values, but there's no single value that matches both filters. What this rule is saying is that a single element in the list must match all rules. If this were the only rule, you'd be okay, since a User with favorite colors including "red" but not "yellow" would have an element that matches all the rules ("red"). The problem is that there's another rule for how queries are executed: Rule 2: The != operator actually performs 2 queries: one where all other filters are the same and the not-equal filter is replaced with a less-than filter, and one where the not-equal filter is replaced with a greater-than filter. The results are merged, in order. This second rule basically means that in your case, the query is split into two queries: SELECT * FROM User WHERE favorite_colors = 'yellow' AND favorite_colors < 'red' and SELECT * FROM User WHERE favorite_colors = 'yellow' AND favorite_colors > 'red' Inequality filters on Strings are based on lexicographical sort (in this case, just alphabetical), so the first query returns an empty set, since it is impossible for any list to contain an element that is both 'yellow' and less than 'red' ('yellow' < 'red' == false). The second query returns any User that has a list containing 'yellow', since 'yellow' is always greater than 'red'. On Sun, Dec 13, 2009 at 6:14 AM, jbochi <[email protected]> wrote: > Hi, > > I have the following model of Users and I want to get all the users > that like 'yellow', but don't like 'red'. > > class User(db.Model): > name = db.StringProperty(required=True) > favorite_colors = db.StringListProperty(required=True) > > This works (all users that have at least one favorite color 'yellow' > are returned): > > results = db.GqlQuery( > "SELECT * FROM User " > "WHERE favorite_colors = 'yellow'") > > But this does not do what I expected: > > results = db.GqlQuery( > "SELECT * FROM User " > "WHERE favorite_colors = 'yellow' " > "and favorite_colors != 'red'") > > The same list of users is returned. I believe that it's testing if any > of the favorite colors are different from 'red' and not if the list > does not contain 'red' at all. > > How can I filter only the results that contain an item and not another > one? > > -- > > You received this message because you are subscribed to the Google Groups > "Google App Engine" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]<google-appengine%[email protected]> > . > For more options, visit this group at > http://groups.google.com/group/google-appengine?hl=en. > > > -- Ikai Lan Developer Programs Engineer, Google App Engine -- You received this message because you are subscribed to the Google Groups "Google App Engine" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en.
