shouts load query factory fixes

This commit is contained in:
tonyrewin 2022-11-20 06:41:05 +03:00
parent 7b8dac062a
commit 35a3d75fe6

View File

@ -1,12 +1,12 @@
#!/usr/bin/env python3.10
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 selectinload
from sqlalchemy.sql.expression import or_, desc, asc, select, case from sqlalchemy.sql.expression import desc, asc, select, case
from timeit import default_timer as timer
from auth.authenticate import login_required from auth.authenticate import login_required
from base.orm import local_session from base.orm import local_session
from base.resolvers import mutation, query from base.resolvers import mutation, query
from orm.shout import Shout, ShoutAuthor from orm.shout import Shout
from orm.reaction import Reaction, ReactionKind from orm.reaction import Reaction, ReactionKind
# from resolvers.community import community_follow, community_unfollow # from resolvers.community import community_follow, community_unfollow
from resolvers.profile import author_follow, author_unfollow from resolvers.profile import author_follow, author_unfollow
@ -55,7 +55,7 @@ async def load_shouts_by(_, info, options):
""" """
q = select(Shout).options( q = select(Shout).options(
# TODO add cation # TODO add caption
selectinload(Shout.authors), selectinload(Shout.authors),
selectinload(Shout.topics), selectinload(Shout.topics),
).where( ).where(
@ -67,10 +67,7 @@ async def load_shouts_by(_, info, options):
user = info.context["request"].user user = info.context["request"].user
q.join(Reaction, Reaction.createdBy == user.slug) q.join(Reaction, Reaction.createdBy == user.slug)
if options.get("filters").get("visibility"): if options.get("filters").get("visibility"):
q = q.filter(or_( q = q.filter(Shout.visibility == options.get("filters").get("visibility"))
Shout.visibility.ilike(f"%{options.get('filters').get('visibility')}%"),
Shout.visibility.ilike(f"%{'public'}%"),
))
if options.get("filters").get("layout"): if options.get("filters").get("layout"):
q = q.filter(Shout.layout == options.get("filters").get("layout")) q = q.filter(Shout.layout == options.get("filters").get("layout"))
if options.get("filters").get("author"): if options.get("filters").get("author"):
@ -84,13 +81,16 @@ async def load_shouts_by(_, info, options):
if options.get("filters").get("days"): if options.get("filters").get("days"):
before = datetime.now() - timedelta(days=int(options.get("filter").get("days")) or 30) before = datetime.now() - timedelta(days=int(options.get("filter").get("days")) or 30)
q = q.filter(Shout.createdAt > before) q = q.filter(Shout.createdAt > before)
o = options.get("order_by")
if options.get("order_by") == 'comments': if o:
q = q.join(Reaction, Shout.slug == Reaction.shout and Reaction.body.is_not(None)).add_columns( q = q.add_columns(sa.func.count(Reaction.id).label(o))
sa.func.count(Reaction.id).label(options.get("order_by"))) if o == 'comments':
if options.get("order_by") == 'reacted': q = q.join(Reaction, Shout.slug == Reaction.shout)
q = q.join(Reaction).add_columns(sa.func.max(Reaction.createdAt).label(options.get("order_by"))) q = q.filter(Reaction.body.is_not(None))
if options.get("order_by") == "rating": elif o == 'reacted':
q = q.join(Reaction).add_columns(sa.func.max(
Reaction.createdAt).label(options.get("order_by")))
elif o == "rating":
q = q.join(Reaction).add_columns(sa.func.sum(case( q = q.join(Reaction).add_columns(sa.func.sum(case(
(Reaction.kind == ReactionKind.AGREE, 1), (Reaction.kind == ReactionKind.AGREE, 1),
(Reaction.kind == ReactionKind.DISAGREE, -1), (Reaction.kind == ReactionKind.DISAGREE, -1),
@ -102,31 +102,22 @@ async def load_shouts_by(_, info, options):
(Reaction.kind == ReactionKind.DISLIKE, -1), (Reaction.kind == ReactionKind.DISLIKE, -1),
else_=0 else_=0
)).label(options.get("order_by"))) )).label(options.get("order_by")))
# if order_by == 'views': order_by = o
# TODO dump ackee data to db periodically else:
order_by = 'createdAt'
order_by = options.get("order_by") if options.get("order_by") else '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')
query_order_by = desc(order_by) if order_by_desc else asc(order_by) query_order_by = desc(order_by) if order_by_desc else asc(order_by)
offset = options.get("offset") if options.get("offset") else 0
q = q.group_by(Shout.id).order_by(query_order_by).limit(options.get("limit")).offset( limit = options.get("limit") or 10
options.get("offset") if options.get("offset") else 0) 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:
# post query stats and author's captions
# start = timer()
shouts = list(map(lambda r: r.Shout, session.execute(q))) shouts = list(map(lambda r: r.Shout, session.execute(q)))
for s in shouts: for s in shouts:
s.stat = await ReactedStorage.get_shout_stat(s.slug) s.stat = await ReactedStorage.get_shout_stat(s.slug)
for a in s.authors: for a in s.authors:
a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug) a.caption = await ShoutAuthorStorage.get_author_caption(s.slug, a.slug)
# end = timer()
# print(end - start)
# print(q)
return shouts return shouts