diff --git a/resolvers/author.py b/resolvers/author.py index 84eb06c1..c38cf317 100644 --- a/resolvers/author.py +++ b/resolvers/author.py @@ -60,17 +60,21 @@ async def get_author(_, _info, slug='', author_id=0): author_dict = None try: author_query = select(Author).filter(or_(Author.slug == slug, Author.id == author_id)) - [author] = await get_authors_with_stat_cached(author_query) - if isinstance(author, Author): - author_id = author.id - logger.debug(f'found @{slug} with id {author_id}') - if not author.stat or not author.stat.get('rating_shouts'): - [author] = get_with_stat(author_query) # FIXME: with_rating=True) - if author: - await set_author_cache(author.dict()) - logger.debug('updated author stored in cache') + result = await get_authors_with_stat_cached(author_query) + if not result: + raise ValueError('Author not found') + [author] = result + author_id = author.id + logger.debug(f'found @{slug} with id {author_id}') if isinstance(author, Author): + if not author.stat: + [author] = get_with_stat(author_query) # FIXME: with_rating=True) + if author: + await set_author_cache(author.dict()) + logger.debug('updated author stored in cache') author_dict = author.dict() + except ValueError: + pass except Exception: import traceback diff --git a/resolvers/rating.py b/resolvers/rating.py index 0135c24f..2bcf6f77 100644 --- a/resolvers/rating.py +++ b/resolvers/rating.py @@ -103,18 +103,7 @@ def count_author_shouts_rating(session, author_id) -> int: return shouts_likes - shouts_dislikes -def load_author_ratings(session, author: Author): - comments_count = ( - session.query(Reaction) - .filter( - and_( - Reaction.created_by == author.id, - Reaction.kind == ReactionKind.COMMENT.value, - Reaction.deleted_at.is_(None), - ) - ) - .count() - ) +def get_author_rating_old(session, author: Author): likes_count = ( session.query(AuthorRating) .filter(and_(AuthorRating.author == author.id, AuthorRating.plus.is_(True))) @@ -125,21 +114,72 @@ def load_author_ratings(session, author: Author): .filter(and_(AuthorRating.author == author.id, AuthorRating.plus.is_not(True))) .count() ) - author.stat = author.stat if isinstance(author.stat, dict) else {} - author.stat['rating'] = likes_count - dislikes_count - author.stat['rating_shouts'] = count_author_shouts_rating(session, author.id) - author.stat['rating_comments'] = count_author_comments_rating(session, author.id) - author.stat['commented'] = comments_count - return author + return likes_count - dislikes_count -def add_rating_columns(q, group_list): +def get_author_rating_shouts(session, author: Author) -> int: + q = ( + select( + func.coalesce(func.sum( + case( + (Reaction.kind == ReactionKind.LIKE.value, 1), + (Reaction.kind == ReactionKind.DISLIKE.value, -1), + else_=0 + ) + ), 0).label('shouts_rating') + ) + .select_from(Reaction) + .outerjoin( + Shout, + Shout.authors.any(id=author.id) + ) + .outerjoin( + Reaction, + and_( + Reaction.reply_to.is_(None), + Reaction.shout == Shout.id, + Reaction.deleted_at.is_(None), + ), + ) + ) + result = session.execute(q).scalar() + return result + + +def get_author_rating_comments(session, author: Author) -> int: + replied_comment = aliased(Reaction) + q = ( + select( + func.coalesce(func.sum( + case( + (Reaction.kind == ReactionKind.LIKE.value, 1), + (Reaction.kind == ReactionKind.DISLIKE.value, -1), + else_=0 + ) + ), 0).label('shouts_rating') + ) + .select_from(Reaction) + .outerjoin( + Reaction, + and_( + replied_comment.kind == ReactionKind.COMMENT.value, + replied_comment.created_by == author.id, + Reaction.kind.in_([ReactionKind.LIKE.value, ReactionKind.DISLIKE.value]), + Reaction.reply_to == replied_comment.id, + Reaction.deleted_at.is_(None), + ), + ) + ) + result = session.execute(q).scalar() + return result + + +def add_author_rating_columns(q, group_list): + # NOTE: method is not used + # old karma q = q.outerjoin(AuthorRating, AuthorRating.author == Author.id) - q = q.add_columns( - func.sum(case((AuthorRating.plus == true(), 1), else_=0)).label('likes_count'), - func.sum(case((AuthorRating.plus != true(), 1), else_=0)).label('dislikes_count'), - ) + q = q.add_columns(func.sum(case((AuthorRating.plus == true(), 1), else_=-1)).label('rating')) # by shouts rating shout_reaction = aliased(Reaction) diff --git a/resolvers/stat.py b/resolvers/stat.py index 787c4bcf..03dd274e 100644 --- a/resolvers/stat.py +++ b/resolvers/stat.py @@ -4,7 +4,7 @@ from sqlalchemy import func, distinct, select, join, and_ from sqlalchemy.orm import aliased from orm.reaction import Reaction, ReactionKind -from resolvers.rating import add_rating_columns +from resolvers.rating import add_author_rating_columns from orm.topic import TopicFollower, Topic from services.db import local_session from orm.author import AuthorFollower, Author @@ -107,7 +107,7 @@ def add_author_stat_columns(q, with_rating=False): group_list = [Author.id, sub_comments.c.comments_count] if with_rating: - q, group_list = add_rating_columns(q, group_list) + q, group_list = add_author_rating_columns(q, group_list) q = q.group_by(*group_list)