Aggregating records

Suppose you have some users and want to get a list of them along with the count of tweets in each.

  1. query = (User
  2. .select(User, fn.Count(Tweet.id).alias('count'))
  3. .join(Tweet, JOIN.LEFT_OUTER)
  4. .group_by(User))

The resulting query will return User objects with all their normal attributes plus an additional attribute count which will contain the count of tweets for each user. We use a left outer join to include users who have no tweets.

Let’s assume you have a tagging application and want to find tags that have a certain number of related objects. For this example we’ll use some different models in a many-to-many configuration:

  1. class Photo(Model):
  2. image = CharField()
  3. class Tag(Model):
  4. name = CharField()
  5. class PhotoTag(Model):
  6. photo = ForeignKeyField(Photo)
  7. tag = ForeignKeyField(Tag)

Now say we want to find tags that have at least 5 photos associated with them:

  1. query = (Tag
  2. .select()
  3. .join(PhotoTag)
  4. .join(Photo)
  5. .group_by(Tag)
  6. .having(fn.Count(Photo.id) > 5))

This query is equivalent to the following SQL:

  1. SELECT t1."id", t1."name"
  2. FROM "tag" AS t1
  3. INNER JOIN "phototag" AS t2 ON t1."id" = t2."tag_id"
  4. INNER JOIN "photo" AS t3 ON t2."photo_id" = t3."id"
  5. GROUP BY t1."id", t1."name"
  6. HAVING Count(t3."id") > 5

Suppose we want to grab the associated count and store it on the tag:

  1. query = (Tag
  2. .select(Tag, fn.Count(Photo.id).alias('count'))
  3. .join(PhotoTag)
  4. .join(Photo)
  5. .group_by(Tag)
  6. .having(fn.Count(Photo.id) > 5))