Search code examples
sqldatabasegoogle-app-enginegqlgqlquery

How to extract data from two GQL classes?


I have the following 2 classes:

class UsersRSS(db.Model):
    userId = db.IntegerProperty()
    fileHash = db.StringProperty()
    added = db.DateTimeProperty(auto_now_add=True)

class Files(db.Model):
    fileHash = db.StringProperty()
    title = db.StringProperty()
    file = db.BlobProperty()
    added = db.DateTimeProperty(auto_now_add=True)    

I need to create a GQL query, which will return a data from both tables:

items = UsersRSS.gql("WHERE userId = :userId ORDER BY date DESC LIMIT 10", userId=user_id)

But each item besides fileHash and added fields, should contain fields from the second class - title and file (matching should be done by fileHash field).


Solution

  • There's no way to retrieve from Datastore different Kinds using the same GQL Select statement.

    Another option would be using the ReferenceProperty to create a many-to-one relationship between UsersRSS and Files, refactoring your code in this way:

    class UsersRSS(db.Model):
        userId = db.IntegerProperty()
        file = db.ReferenceProperty(Files)
        added = db.DateTimeProperty(auto_now_add=True)
    
    class Files(db.Model):
        fileHash = db.StringProperty()
        title = db.StringProperty()
        file = db.BlobProperty()
        added = db.DateTimeProperty(auto_now_add=True)
    
    items = UsersRSS.gql("WHERE userId = :userId ORDER BY date DESC LIMIT 10", userId=user_id)
    

    In this way, the Files properties will be automatically dereferenced using the item.file.title dot notation:

    for item in items:
        print item.UserID
        print item.Added
        print item.file.title #This costs an additional RPC call to Datastore
    

    To save your App from the ReferenceProperty RPC overhead have a look to the evergreen article ReferenceProperty prefetching.