Home > Python > Tagging with Appengine DataStore

Tagging with Appengine DataStore

by paul on November 7, 2009

I’ve been looking into how to implement a tagging mechanism with Appengine (Python). By using a StringListProperty, you can associate a list of tags with an entity. The model would look something like this:

from google.appengine.ext import db

class Sample(db.Model):
  name = db.StringProperty(required=True)
  tags = db.StringListProperty()

Now, assuming we want to find the entities tagged with a given word, we can use a query like this:

q = db.GqlQuery(“SELECT * FROM Sample where tags = :1″,’z')

If we want to find all entities that have ANY of these tags (OR) we can query with GqlQuery or filter:

q = db.GqlQuery(“SELECT * FROM Sample where tags in :1″,['a','z'])

q = domain.Sample.all()
q.filter(“tags in “, ['b','d'])

When we want to find entities with ALL of the given tags:

q = db.GqlQuery(“SELECT * FROM Sample where tags = :1 and tags = :2″,’b',’c')
q = domain.Sample.all()
q.filter(“tags = “, ‘b’)
q.filter(“tags = “, ‘c’)

Too easy!

If you have an appengine project, you can try this code out by adding the entity (Sample – listed above) to your domain model and run the following in your development console (http://localhost:8080/_ah/admin/interactive):

import domain

domain.Sample(name='t1',tags=['a','b','c']).put()
domain.Sample(name='t2',tags=['b','c','d']).put()
domain.Sample(name='t3',tags=['c','d','e']).put()
domain.Sample(name='t3',tags=['x','Y','z']).put()

def display(r):
 for r in results:
  print r.name +" tags = "+' '.join(r.tags)

print "FIND WITH THIS TAG"
q = db.GqlQuery("SELECT * FROM Sample where tags = :1",'z')
results = q.fetch(5)
display(results)

print "FIND WITH ANY OF THESE TAGS (OR)"
q = db.GqlQuery("SELECT * FROM Sample where tags in :1",['a','z'])
results = q.fetch(5)
display(results)

print "FIND WITH ANY OF THESE TAGS (OR)"
q = domain.Sample.all()
q.filter("tags in ", ['a','z'])
results = q.fetch(5)
display(results)

print "FIND WITH ANY OF THESE TAGS (AND)"
q = db.GqlQuery("SELECT * FROM Sample where tags = :1 and tags = :2",'b','c')
results = q.fetch(5)
display(results)

print "FIND WITH ALL OF THESE TAGS (AND)"
q = domain.Sample.all()
q.filter("tags = ", 'b')
q.filter("tags = ", 'c')

results = q.fetch(5)
display(results)

This should produce the following result:

FIND WITH THIS TAG
t3 tags = x Y z
FIND WITH ANY OF THESE TAGS (OR)
t1 tags = a b c
t3 tags = x Y z
FIND WITH ANY OF THESE TAGS (OR)
t1 tags = a b c
t3 tags = x Y z
FIND WITH ANY OF THESE TAGS (AND)
t1 tags = a b c
t2 tags = b c d
FIND WITH ALL OF THESE TAGS (AND)
t1 tags = a b c
t2 tags = b c d

So, it’s easier than I thought. But I’m not experienced with DataStore yet, and I don’t know if there are inherit limitations with this approach – remember, there are limits on the way you retrieve data.

Leave a Comment

Previous post:

Next post: