30 votes

Quelle est la meilleure façon de compter les résultats dans GQL?

Je pense qu'une façon de faire un décompte est la suivante:

 foo = db.GqlQuery("SELECT * FROM bar WHERE baz = 'baz')
my_count = foo.count()
 

Ce que je n'aime pas, c'est que mon nombre sera limité à 1000 max et ma requête sera probablement lente. Quelqu'un avec une solution de contournement? J'en ai un en tête, mais ça ne me semble pas propre. Si seulement GQL avait une vraie fonction COUNT ...

20voto

Jehiah Points 1467

Vous devez retourner votre pensée lorsque vous travaillez avec une solution évolutive de la banque de données comme GAE à faire vos calculs avant. Dans ce cas, cela signifie que vous devez garder les compteurs pour chaque baz et d'un incrément à chaque fois que vous ajoutez un nouveau bar, au lieu de compter au moment de l'affichage.

class CategoryCounter(db.Model):
    category = db.StringProperty()
    count = db.IntegerProperty(default=0)

ensuite, lors de la création d'une Barre d'objet, d'incrémenter le compteur

def createNewBar(category_name):
  bar = Bar(...,baz=category_name)

  counter = CategoryCounter.filter('category =',category_name).get()
  if not counter:
    counter = CategoryCounter(category=category_name)
  else:
    counter.count += 1
  bar.put()
  counter.put()

db.run_in_transaction(createNewBar,'asdf')

vous avez maintenant un moyen facile d'obtenir le comte pour une catégorie spécifique

CategoryCounter.filter('category =',category_name).get().count

17voto

zgoda Points 8549

+1 à la réponse de Jehiah.

La méthode officielle et bénie pour obtenir des compteurs d'objets sur GAE est de construire un compteur fragmenté . Malgré un nom qui sonne lourdement, c'est assez simple.

7voto

Nick Johnson Points 79909

Les fonctions de comptage dans toutes les bases de données sont lentes (par exemple, O (n)) - la banque de données GAE rend cela plus évident. Comme le suggère Jehiah, vous devez stocker le nombre calculé dans une entité et y faire référence si vous souhaitez une évolutivité.

Ce n'est pas unique à App Engine - d'autres bases de données le cachent mieux, jusqu'au point où vous essayez de compter des dizaines de milliers d'enregistrements à chaque demande, et le temps de rendu de votre page commence à augmenter de façon exponentielle ...

2voto

rescdsk Points 4136

Selon la GqlQuery.count() de la documentation, vous pouvez définir l' limit être un certain nombre supérieur à 1000:

from models import Troll
troll_count = Troll.all(keys_only=True).count(limit=31337)

Fragmenté compteurs sont dans le bon sens de garder une trace des numéros comme ça, que les gens ont dit, mais si vous trouver cela en retard dans le jeu (comme moi), puis vous aurez besoin d'initialiser les compteurs à partir d'un nombre réel des objets. Mais c'est un excellent moyen de brûler par le biais de votre quota gratuit de la banque de données des Petites entreprises (de 50 000 je crois). Chaque fois que vous exécutez le code, il va utiliser comme de nombreux ops comme il y a des objets de modèle.

0voto

orip Points 28225

Je ne l'ai pas essayé, et c'est un porc de ressources absolu, mais peut-être qu'itérer avec .fetch() et spécifier le décalage fonctionnerait?

 LIMIT=1000
def count(query):
   result = offset = 0
   gql_query = db.GqlQuery(query)
   while True:
     count = gql_query.fetch(LIMIT, offset)
     if count < LIMIT:
       return result
     result += count
     offset += LIMIT
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X