Friday, December 7, 2012

Join Query on Google App Engine Datastore

App Engine Datastore is a no sql database. That means you cannot  do standard sql queries. But they do have the basic queries using GQL. It is a no SQL database which is very reliable, does not slow down even with terabytes of data, and has a nice indexing mechanism to fetch data.

You can use Google Cloud SQL if you need a relational database, it's a manage mySQL database by google. By the time I'm writing this, they now support up to 100GB of mySQL database, but still limited to the limitations of a standard mySQL and it's coolness.

So if you really can't avoid a de-normalize table like you want to show the name of a user in a list, I'll show you samples. This will all be using python 2.7 and ndb.


from google.appengine.ext import ndb
# just a sample model for how to efficiently join them
class User(ndb.Model):
    name = ndb.StringProperty()
    photo = ndb.BlobKeyProperty()
    """
    always create a text version of your blobkey and store
    the result of images.get_serving_url(blob) to it one time if
    your app allows it
    """    
    photo_path = ndb.TextProperty()

class Page(ndb.Model):
    data = ndb.TextProperty()

class Comment(ndb.Model):
    user = ndb.KeyProperty()
    page = ndb.KeyProperty()
    created = ndb.DateTimeProperty(auto_now_add=True)
    message = ndb.TextProperty()

    @classmethod
    @ndb.tasklet
    def get_comment_async(comment):
        result = comment.to_dict()
        user = yield comment.user.get_async()
        result['user'] = { 'name' : user.name, 'photo' : user.photo_path }
        raise ndb.Return(result)

# on your handler
class MainHandler(webapp.RequestHandler):
    def get(self):
        page = Page.get_by_id(self.request.get('id'))
        # now we query comments of the page
        comments = Comment.query(Comment.page == page.key)
                          .order(-Comment.created).fetch()
        futures = []
        # another good use of tasklet is to load fields info asynchronously
        for comment in comments:
            futures.append(yield Comment.get_comment_async(comment))
        # ndb will try to batch what it can so it only does few network hops
        ndb.Future.wait_all(futures)
        # pass your results to your view
        view_data['comments'] = [future.get_result() for future in futures]

5 comments:

  1. This is my first visit to your web journal! We are a group of volunteers and new activities in the same specialty. Website gave us helpful data to work. Buy Google Places Reviews

    ReplyDelete
  2. buenos dias mi amor Very informative information on your site here. I like this post because we can get some useful information from your blog. I expect more post from you

    ReplyDelete
  3. buenos dias mi amor Very informative information on your site here. I like this post because we can get some useful information from your blog. I expect more post from you

    ReplyDelete
  4. In this way, Google enables you to let them know on a size of 0.0 to 1.0 how significant a given page is comparative with all the others. Utilizing this framework, you may disclose to Google that your landing page is a 1.0, every one of your item areas is a 0.8, and every one of your individual item pages is a 0.5. Pages like your organization's location and contact data may just rate a 0.2. finance

    ReplyDelete