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.


Reply via email to