Using referenced class properties in GQL Query WHERE clause

94 views
Skip to first unread message

olex13

unread,
Apr 14, 2009, 1:04:59 PM4/14/09
to Google App Engine
Hi,

Is it possible to use referenced-class properties in GQL query, like:

Thread.gql("WHERE user.email = :1", email)

class Thread(db.Model)
user = dbReferenceProperty(User)

class User(db.Model)
email = db.EmailProperty()

It seems logical to support this but I get: BadQueryError: Parse
Error: Invalid WHERE Condition at symbol .email

--
Olex

JDT

unread,
Apr 15, 2009, 7:18:45 AM4/15/09
to Google App Engine
A naive question: I note that in this snippet you have User(db.model)
and user.email.
Is this a python case sensitivity issue? i.e. User != user ?

D

olex13

unread,
Apr 15, 2009, 7:28:45 AM4/15/09
to Google App Engine
Hmm, didn't get your point

Here:

--
class Thread(db.Model)
user = dbReferenceProperty(User)
--

User - name of referenced class
user - field name in Thread class

so I'm trying to navigate on the field property:

Thread.gql("WHERE user.email = :1", email)

PS
well, I checked: Thread.gql("WHERE User.email = :1", email)
raise the same error

On 15 Кві, 14:18, JDT <john.david....@googlemail.com> wrote:
> A naive question: I note that in this snippet you have User(db.model)
> and user.email.
> Is this a python case sensitivity issue? i.e. User != user ?
>
> D
>

风笑雪

unread,
Apr 15, 2009, 8:27:05 AM4/15/09
to google-a...@googlegroups.com
Seems you can do it. Remember it: it's not a relationship DB, you should organize an entity as how you use it.

If you just want email to identify a thread, you can simply define:

class Thread(db.Mode):
  email = db.EmailProperty()

or this is ok too:

class Thread(db.Mode):
  user = db.UserProperty()
  user_email = db.EmailProperty()

You need to know the query need an index.
When you perform a query on Thread, its index doesn't contain a attribute of user.email, so that would be wrong. NOTE: The Thread class only has index on user, not user.email.

If you don't want change your model, you can only do it this way:

user = User.gql('WHERE email = :1', email)
threads = user.user_set
for thread in threads:
  ...

The '_set' means a back-reference property.

You can get more details in "References" of "Entities and Models" document: 

2009/4/15 olex13 <olexandr....@gmail.com>

风笑雪

unread,
Apr 15, 2009, 8:32:06 AM4/15/09
to google-a...@googlegroups.com
Sorry I forgot to fetch.

user = User.gql('WHERE email = :1', email).get()
threads = user.user_set  # if they are 1:1 relationship, it would be ok: thread = user.user_set[0]
for thread in threads:
  ...

2009/4/15 风笑雪 <kea...@gmail.com>

风笑雪

unread,
Apr 15, 2009, 9:01:36 AM4/15/09
to google-a...@googlegroups.com
Well, a mistake again...user.thread_set, not user.user_set

Give you an example:

class User(db.Model):
  email = db.EmailProperty()

class Thread(db.Model):
  user = db.ReferenceProperty(User)

class Foo(webapp.RequestHandler):
  def get(self):
    user = User(email='kea...@gmail.com')
    user.put()  # NOTE: you need save it before reference it
    thread = Thread(user=user).put()

class Bar(webapp.RequestHandler):
  def get(self):
    user = User.gql('WHERE email = :1', 'kea...@gmail.com').get()
    thread = user.thread_set[0]
    if thread
      self.response.out.write(thread.user.email)
    

2009/4/15 风笑雪 <kea...@gmail.com>

olex13

unread,
Apr 15, 2009, 9:55:30 AM4/15/09
to Google App Engine
Thank you, explanations are very clear!

I will go with this version:

class Thread(db.Mode):
user = db.UserProperty()
user_email = db.EmailProperty()

+ index on user_email

BR, Olex
> >>http://code.google.com/appengine/docs/python/datastore/entitiesandmod...
>
> >> 2009/4/15 olex13 <olexandr.kundire...@gmail.com>
Reply all
Reply to author
Forward
0 new messages