views:

77

answers:

1

What I'm trying to do is query the datastore for a model where the key is not the key of an object I already have. Here's some code:

class User(db.Model):
    partner = db.SelfReferenceProperty()

def text_message(self, msg):
    user = User.get_or_insert(msg.sender)

    if not user.partner:
        # user doesn't have a partner, find them one
        # BUG: this line returns 'user' himself... :(
        other = db.Query(User).filter('partner =', None).get()
        if other:
            # connect users
        else:
            # no one to connect to!

The idea is to find another User who doesn't have a partner, that isn't the user we already know.

I've tried filter('key !=, user.key()), filter('__key__ !=, user.key()) and a couple others, and nothing returns another User who doesn't have a partner. filter('foo !=, user.key()) also returns nothing, for the record.

+1  A: 

There's a really easy way around this: Retrieve two records, and filter out the user's own one, if it's present.

def text_message(self, msg):
    user = User.get_or_insert(msg.sender)

    if not user.partner:
        # user doesn't have a partner, find them one
        other = db.Query(User).filter('partner =', None).fetch(2)
        other = [u for u in other if u.key() != user.key()]
        if other:
            # connect user with other[0]
        else:
            # no one to connect to!
Nick Johnson
I thought about this, and it would definitely work, but it seems like a hack. Is it not possible to just filter by key in a query?
Jason Hall
It is possible, and your queries should work - without more details I can't tell you why they're not. However, they'd also be substantially _less_ efficient than this approach: != queries require two underlying queries to execute, which is a bit of a blunt instrument just to eliminate a single result from the result set.
Nick Johnson
Oh, then fetching two is actually better? Interesting. Here's my code if you're curious: http://gist.github.com/344873
Jason Hall
Yes, fetching two will definitely be better than two separate queries. This is also the approach taken by the crowdguru sample app: http://code.google.com/p/google-app-engine-samples/source/browse/trunk/crowdguru/guru.py#98
Nick Johnson