2010-11-22 7 views
3

J'essaie de déterminer le moyen le plus efficace de créer une entité votable sur le magasin de données de GAE. Je voudrais montrer à l'utilisateur un contrôle pour voter pour cette entité ou une icône indiquant qu'ils ont déjà voté pour cette entité; c'est-à-dire, je demande "a un utilisateur a voté sur cette entité?" Disons que nous avons une entité Question qu'un utilisateur peut voter. Voici ce que je pense faire:Modélisation des votes sur GAE

  1. Requête pour mes entités Question. Ces questions ont déjà un classement précalculé sur lequel je vais trier.
  2. Utilisez une entité d'index de relation qui est un enfant de l'entité Question. Requête pour toutes les questions utilisant les mêmes filtres que # 1 où mon utilisateur est membre de cette entité d'index de relation.
  3. Fusionnez les résultats de # 2 en # 1 en définissant une propriété hasVoted sur true pour chaque membre d'ensemble trouvé.

Ceci est la façon la plus propre que je pourrais penser de le faire, mais il nécessite encore deux requêtes. Je n'ai pas créé d'entités Question dupliquées pour chaque utilisateur, car cela entraînerait trop de duplication de données. Est-ce que cette solution est un bon moyen de gérer ce qui est effectivement une jointure entre une relation m2m entre votes et questions ou est-ce que je pense trop en relation?

Répondre

0

Pour éviter la deuxième requête, vous pouvez stocker tous les des questions pour lesquelles un utilisateur a voté dans une seule entité. Cette entité peut faire partie du modèle User ou exister dans une relation un-à-un avec les entités User. Vous pouvez ensuite charger ces informations si nécessaire (et les stocker dans memcache pour éviter les charges de banque de données) afin de pouvoir vérifier rapidement si un utilisateur a déjà voté sur une question (sans faire une seconde requête la plupart du temps).

Si un utilisateur peut voter sur un très grand nombre de questions, vous devrez peut-être étendre cette idée. Voici un aperçu (non fonctionnel complet) de la façon dont vous pouvez aller sur le schéma simple:

class UserVotes(db.Model): 
    # key = key_name or ID of the corresponding user entity 

    # if all of your question entities have IDs, then voted_on can be a list of 
    # integers; otherwise it can be a list of strings (key_name values) 
    voted_on = db.ListProperty(int, indexed=False) 

# in your request handler ... 
questions = ... 
voted_on = memcache.get('voted-on:%s' % user_id) 
if voted_on is None: 
    voted_on = UserVotes.get_by_id(user_id) # should do get_or_insert() instead 
    memcache.set(...) 
for q in questions: 
    q.has_voted = q.key().id() in voted_on 
+1

Je remplacerais 'si non voté par:' avec 'si voté_on est Aucun:' parce que si 'voté_on = []' que 'si non coted_on: 'est Vrai. –

+0

Bon point Vladimir; J'ai modifié le code - merci! –

+0

@ David- ne serait-il pas plus simple de créer un 'db.ListProperty (db.Key)' sur l'utilisateur appelé user_votes, qui contient les clés des questions votées par l'utilisateur? – Yarin

3

Au lieu d'utiliser un indice de relation, ont juste une entité enfant pour chaque utilisateur qui a voté sur la question. Faites de l'ID de la clé de l'entité enfant l'ID de l'utilisateur. Ensuite, pour déterminer si un utilisateur y a voté sur une question avec l'ID x, il suffit de récupérer la clé (Question: x/Vote: y). Vous pouvez aussi charger ceci pour récupérer plusieurs entités pour plusieurs questions ou utilisateurs.

+0

Pourquoi avez-vous suggéré de garder les entités enfants du côté de la question, et non du côté de l'utilisateur? Si une question est populaire, ne passerait-elle pas la limite d'écriture maximale du groupe d'entités de questions? Y a-t-il des inconvénients à garder les votes du côté des utilisateurs? – ali

+0

@ali Avoir des votes être des entités enfant de la question vous permet de faire un seul chargement atomique pour tous les votes pour obtenir un compte précis. –

+0

Le nombre de votes ne doit-il pas être stocké en tant que propriété de l'entité de question? – ali

2

Je voudrais jeter un oeil à Overheard exemple d'application Google App Engine.

Notre modèle de base sera d'avoir citations, qui contiennent une chaîne pour la citation et votes, qui contiennent le nom d'utilisateur et voter pour un utilisateur particulier.

Il ya un Google article à ce sujet et here vous pouvez trouver les sources.