loadShouts gotta go fast

This commit is contained in:
Igor Lobanov 2022-11-23 22:53:53 +01:00
parent 82be2da3d8
commit 4ef990eadf
2 changed files with 34 additions and 26 deletions

View File

@ -1,6 +1,6 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.orm import selectinload from sqlalchemy.orm import joinedload
from sqlalchemy.sql.expression import desc, asc, select, case from sqlalchemy.sql.expression import desc, asc, select, case
from base.orm import local_session from base.orm import local_session
from base.resolvers import query from base.resolvers import query
@ -37,8 +37,8 @@ async def load_shout(_, info, slug):
with local_session() as session: with local_session() as session:
shout = session.query(Shout).options( shout = session.query(Shout).options(
# TODO add cation # TODO add cation
selectinload(Shout.authors), joinedload(Shout.authors),
selectinload(Shout.topics), joinedload(Shout.topics),
).filter( ).filter(
Shout.slug == slug Shout.slug == slug
).filter( ).filter(
@ -48,6 +48,12 @@ async def load_shout(_, info, slug):
return shout return shout
def map_result_item(result_item):
shout = result_item[0]
shout.rating = result_item[1]
return shout
@query.field("loadShouts") @query.field("loadShouts")
async def load_shouts_by(_, info, options): async def load_shouts_by(_, info, options):
""" """
@ -71,14 +77,24 @@ async def load_shouts_by(_, info, options):
""" """
q = select(Shout).options( q = select(Shout).options(
# TODO add caption joinedload(Shout.authors),
selectinload(Shout.authors), joinedload(Shout.topics),
selectinload(Shout.topics),
).where( ).where(
Shout.deletedAt.is_(None) Shout.deletedAt.is_(None)
) )
user = info.context["request"].user user = info.context["request"].user
q = apply_filters(q, options.get("filters"), user) q = apply_filters(q, options.get("filters"), user)
q = q.join(Reaction).add_columns(sa.func.sum(case(
(Reaction.kind == ReactionKind.AGREE, 1),
(Reaction.kind == ReactionKind.DISAGREE, -1),
(Reaction.kind == ReactionKind.PROOF, 1),
(Reaction.kind == ReactionKind.DISPROOF, -1),
(Reaction.kind == ReactionKind.ACCEPT, 1),
(Reaction.kind == ReactionKind.REJECT, -1),
(Reaction.kind == ReactionKind.LIKE, 1),
(Reaction.kind == ReactionKind.DISLIKE, -1),
else_=0
)).label('rating'))
o = options.get("order_by") o = options.get("order_by")
if o: if o:
@ -92,21 +108,9 @@ async def load_shouts_by(_, info, options):
).add_columns( ).add_columns(
sa.func.max(Reaction.createdAt).label(o) sa.func.max(Reaction.createdAt).label(o)
) )
elif o == "rating":
q = q.join(Reaction).add_columns(sa.func.sum(case(
(Reaction.kind == ReactionKind.AGREE, 1),
(Reaction.kind == ReactionKind.DISAGREE, -1),
(Reaction.kind == ReactionKind.PROOF, 1),
(Reaction.kind == ReactionKind.DISPROOF, -1),
(Reaction.kind == ReactionKind.ACCEPT, 1),
(Reaction.kind == ReactionKind.REJECT, -1),
(Reaction.kind == ReactionKind.LIKE, 1),
(Reaction.kind == ReactionKind.DISLIKE, -1),
else_=0
)).label(o))
order_by = o order_by = o
else: else:
order_by = 'createdAt' order_by = Shout.createdAt
order_by_desc = True if options.get('order_by_desc') is None else options.get('order_by_desc') order_by_desc = True if options.get('order_by_desc') is None else options.get('order_by_desc')
@ -116,10 +120,13 @@ async def load_shouts_by(_, info, options):
q = q.group_by(Shout.id).order_by(query_order_by).limit(limit).offset(offset) q = q.group_by(Shout.id).order_by(query_order_by).limit(limit).offset(offset)
with local_session() as session: with local_session() as session:
shouts = list(map(lambda r: r.Shout, session.execute(q))) shouts = list(map(map_result_item, session.execute(q).unique()))
for s in shouts:
s.stat = await ReactedStorage.get_shout_stat(s.slug) for shout in shouts:
for a in s.authors: shout.stat = await ReactedStorage.get_shout_stat(shout.slug, shout.rating)
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
del shout.rating
for author in shout.authors:
author.caption = await ShoutAuthorStorage.get_author_caption(shout.slug, author.slug)
return shouts return shouts

View File

@ -34,14 +34,15 @@ class ReactedStorage:
modified_shouts = set([]) modified_shouts = set([])
@staticmethod @staticmethod
async def get_shout_stat(slug): async def get_shout_stat(slug, rating):
viewed = int(await ViewedStorage.get_shout(slug)) viewed = int(await ViewedStorage.get_shout(slug))
# print(viewed) # print(viewed)
return { return {
"viewed": viewed, "viewed": viewed,
"reacted": len(await ReactedStorage.get_shout(slug)), "reacted": len(await ReactedStorage.get_shout(slug)),
"commented": len(await ReactedStorage.get_comments(slug)), "commented": len(await ReactedStorage.get_comments(slug)),
"rating": await ReactedStorage.get_rating(slug), # "rating": await ReactedStorage.get_rating(slug),
"rating": rating
} }
@staticmethod @staticmethod