Modèles de données de Google AppEngine

Face à la problématique du portage en environnement Google AppEngine d'une application qui doit gérer des volumes de données importantes, il y a quelques bonnes pratiques qu'il faut utiliser absolument. La récente conférence Google IO a été l'occasion de voir une conférence sur le thème de "building scalable application". Les éléments exposés ici ne sont qu'une partie de cette conférence. L'utilisation StringListProperty permet de réduire de manière importante le nombre de Model de données à gérer. Le format de stockage des informations est beaucoup plus dense, et la recherche d'infos est plus simple. La mise en œuvre est très simple, par exemple pour gérer les couleurs favorites d'un utilisateur :

class Favorites(db.Model):
  colors = db.StringListProperty()
  username = db.StringProperty()

fav.colors = ["red", "blue", "green"]

Pour retrouver tous les utilisateurs qui aiment le jaune :

results = db.GqlQuery( "SELECT * FROM FavoriteColors WHERE color = 'yellow'")
users = [r.username for r in results]

Les petites contraintes sont par contre une consommation supérieure de CPU pour la serialisation, et les tris sont un peu plus difficiles à réaliser. Si on compare la façon de laquelle une application de microblogging serait faite avec un outil de base de données classique :

SELECT * FROM Messages INNER JOIN UserMessages 
USING (message_id) WHERE UserMessages.user_id = 'X';

Et maintenant avec App Engine :

class Message(db.Model):
  sender = db.StringProperty()
  receivers = db.StringListProperty()
  body = db.TextProperty()

results = db.GqlQuery("SELECT * FROM Message WHERE receivers = :1", me)

C'est tout de suite plus simple ! Par contre si les propertylist sont de très grande tailles (plus de 100 items) les performances peuvent être fortement affectées. La solution dans ce cas est de couper l'enregistrement en deux en mettant la liste d'un coté, et les données de l'autre. En SQL ceci nécessiterait de réaliser une complexe jointure entre les 2 tables mais ici c'est immédiatement plus simple.

class Message(db.Model):
  sender = db.StringProperty()
  body = db.TextProperty()

class MessageIndex(db.Model):
  receivers = db.StringListProperty()

indexes = db.GqlQuery("SELECT __key__ FROM MessageIndex WHERE receivers = :1", me)
keys = [k.parent() for k in indexes]
messages = db.get(keys)

Voila pour cette rapide introduction aux structures de données de l'AppEngine. Si il y a vraiment un point qu'il ne faut pas oublier lorsqu'on utilise des outils de type CloudComputing c'est bien la scalabilité. Avec ces bonnes pratiques, c'est bien de toute l'expérience de Google sur le sujet  que vous aller pouvoir profiter .