separate-getter
All checks were successful
Deploy to core / deploy (push) Successful in 1m53s

This commit is contained in:
Untone 2024-02-23 02:49:34 +03:00
parent 3d34c6c540
commit 392cfb19bd
4 changed files with 63 additions and 49 deletions

View File

@ -10,7 +10,7 @@ from orm.reaction import Reaction, ReactionKind
from orm.shout import Shout, ShoutAuthor, ShoutTopic from orm.shout import Shout, ShoutAuthor, ShoutTopic
from orm.topic import Topic from orm.topic import Topic
from resolvers.follower import query_follows from resolvers.follower import query_follows
from resolvers.stat import add_stat_columns, get_with_stat, unpack_stat from resolvers.stat import get_authors_with_stat
from services.auth import login_required from services.auth import login_required
from services.db import local_session from services.db import local_session
from services.rediscache import redis from services.rediscache import redis
@ -98,7 +98,7 @@ def count_author_shouts_rating(session, author_id) -> int:
def load_author_with_stats(q): def load_author_with_stats(q):
result = get_with_stat(q, Author, AuthorFollower) result = get_authors_with_stat(q)
if result: if result:
[author] = result [author] = result
@ -199,7 +199,7 @@ def load_authors_by(_, _info, by, limit, offset):
q = q.limit(limit).offset(offset) q = q.limit(limit).offset(offset)
q = q.group_by(Author.id) q = q.group_by(Author.id)
authors = get_with_stat(q, Author, AuthorFollower) authors = get_authors_with_stat(q)
return authors return authors
@ -269,14 +269,10 @@ def create_author(user_id: str, slug: str, name: str = ''):
@query.field('get_author_followers') @query.field('get_author_followers')
def get_author_followers(_, _info, slug) -> List[Author]: def get_author_followers(_, _info, slug) -> List[Author]:
aliased_author = aliased(Author) q = select(Author)
q = select(aliased_author)
q = ( q = (
q.join(AuthorFollower, AuthorFollower.follower == Author.id) q.join(AuthorFollower, AuthorFollower.follower == Author.id)
.join(aliased_author, aliased_author.id == AuthorFollower.author) .join(Author, Author.id == AuthorFollower.author)
.where(aliased_author.slug == slug) .where(Author.slug == slug)
) )
q = add_stat_columns(q, aliased_author, AuthorFollower) return get_authors_with_stat(q)
q = q.group_by(aliased_author.id)
return unpack_stat(q)

View File

@ -14,7 +14,7 @@ from orm.shout import Shout, ShoutReactionsFollower
from orm.topic import Topic, TopicFollower from orm.topic import Topic, TopicFollower
from resolvers.community import community_follow, community_unfollow from resolvers.community import community_follow, community_unfollow
from resolvers.topic import topic_follow, topic_unfollow from resolvers.topic import topic_follow, topic_unfollow
from resolvers.stat import add_stat_columns, unpack_stat from resolvers.stat import get_topics_with_stat, get_authors_with_stat
from services.auth import login_required from services.auth import login_required
from services.db import local_session from services.db import local_session
from services.follows import DEFAULT_FOLLOWS from services.follows import DEFAULT_FOLLOWS
@ -110,10 +110,8 @@ def query_follows(user_id: str):
.filter(TopicFollower.topic == Topic.id) .filter(TopicFollower.topic == Topic.id)
) )
authors_query = add_stat_columns(authors_query, aliased_author, AuthorFollower) authors = get_authors_with_stat(authors_query)
authors = unpack_stat(authors_query) topics = get_topics_with_stat(topics_query)
topics_query = add_stat_columns(topics_query, aliased_author, TopicFollower)
authors = unpack_stat(topics_query)
return { return {
'topics': topics, 'topics': topics,
@ -226,10 +224,7 @@ def get_topic_followers(_, _info, slug: str, topic_id: int) -> List[Author]:
.join(Topic, Topic.id == TopicFollower.topic) .join(Topic, Topic.id == TopicFollower.topic)
.filter(or_(Topic.slug == slug, Topic.id == topic_id)) .filter(or_(Topic.slug == slug, Topic.id == topic_id))
) )
q = add_stat_columns(q, Author, TopicFollower) return get_authors_with_stat(q)
q = q.group_by(Author.id)
return unpack_stat(q)
@query.field('get_shout_followers') @query.field('get_shout_followers')

View File

@ -1,19 +1,44 @@
from sqlalchemy import func, distinct from sqlalchemy import func, distinct
from sqlalchemy.orm import aliased
from orm.topic import TopicFollower, Topic
from services.db import local_session from services.db import local_session
from orm.author import AuthorFollower from orm.author import AuthorFollower, Author
from orm.shout import ShoutTopic, ShoutAuthor from orm.shout import ShoutTopic, ShoutAuthor
def add_stat_columns(q, author_alias, follower_model_alias): def add_topic_stat_columns(q):
shouts_stat_model = ShoutAuthor if isinstance(follower_model_alias, AuthorFollower) else ShoutTopic aliased_shout_author = aliased(ShoutAuthor)
q = q.outerjoin(shouts_stat_model).add_columns(func.count(distinct(shouts_stat_model.shout)).label('shouts_stat')) aliased_topic_follower = aliased(TopicFollower)
q = q.outerjoin(
follower_model_alias, follower_model_alias.follower == author_alias.id q = (
).add_columns(func.count(distinct(follower_model_alias.author)).label('authors_stat')) q.outerjoin(ShoutTopic, Topic.id == ShoutTopic.topic)
q = q.outerjoin(follower_model_alias, follower_model_alias.author == author_alias.id).add_columns( .add_columns(func.count(distinct(ShoutTopic.shout)).label('shouts_stat'))
func.count(distinct(follower_model_alias.follower)).label('followers_stat') .outerjoin(aliased_shout_author, ShoutTopic.shout == aliased_shout_author.shout)
.add_columns(func.count(distinct(aliased_shout_author.author)).label('authors_stat'))
.outerjoin(aliased_topic_follower)
.add_columns(func.count(distinct(aliased_topic_follower.follower)).label('followers_stat'))
) )
q = q.group_by(Topic.id)
return q
def add_author_stat_columns(q):
aliased_author_followers = aliased(AuthorFollower)
aliased_author_authors = aliased(AuthorFollower)
q = (
q.outerjoin(ShoutAuthor, Author.id == ShoutAuthor.author)
.add_columns(func.count(distinct(ShoutAuthor.shout)).label('shouts_stat'))
.outerjoin(aliased_author_authors, AuthorFollower.follower == Author.id)
.add_columns(func.count(distinct(aliased_author_authors.author)).label('authors_stat'))
.outerjoin(aliased_author_followers)
.add_columns(func.count(distinct(aliased_author_followers.follower)).label('followers_stat'))
)
q = q.group_by(Author.id)
return q return q
@ -31,6 +56,11 @@ def unpack_stat(q):
return records return records
def get_with_stat(q, author_alias, follower_model_alias): def get_authors_with_stat(q):
q = add_stat_columns(q, author_alias, follower_model_alias) q = add_author_stat_columns(q)
return unpack_stat(q)
def get_topics_with_stat(q):
q = add_topic_stat_columns(q)
return unpack_stat(q) return unpack_stat(q)

View File

@ -3,7 +3,7 @@ from sqlalchemy import and_, distinct, func, select
from orm.author import Author from orm.author import Author
from orm.shout import ShoutTopic from orm.shout import ShoutTopic
from orm.topic import Topic, TopicFollower from orm.topic import Topic, TopicFollower
from resolvers.stat import get_with_stat from resolvers.stat import get_topics_with_stat
from services.auth import login_required from services.auth import login_required
from services.db import local_session from services.db import local_session
from services.schema import mutation, query from services.schema import mutation, query
@ -12,22 +12,17 @@ from services.logger import root_logger as logger
@query.field('get_topics_all') @query.field('get_topics_all')
def get_topics_all(_, _info): def get_topics_all(_, _info):
q = select(Topic) return get_topics_with_stat(select(Topic))
q = q.group_by(Topic.id)
topics = get_with_stat(q, Author, TopicFollower)
return topics
@query.field('get_topics_by_community') @query.field('get_topics_by_community')
async def get_topics_by_community(_, _info, community_id: int): def get_topics_by_community(_, _info, community_id: int):
q = select(Topic).where(Topic.community == community_id) q = select(Topic).where(Topic.community == community_id)
q = q.group_by(Topic.id) return get_topics_with_stat(q)
topics = await get_with_stat(q, Author, TopicFollower)
return topics
@query.field('get_topics_by_author') @query.field('get_topics_by_author')
async def get_topics_by_author(_, _info, author_id=None, slug='', user=''): def get_topics_by_author(_, _info, author_id=None, slug='', user=''):
q = select(Topic) q = select(Topic)
if author_id: if author_id:
q = q.join(Author).where(Author.id == author_id) q = q.join(Author).where(Author.id == author_id)
@ -36,23 +31,21 @@ async def get_topics_by_author(_, _info, author_id=None, slug='', user=''):
elif user: elif user:
q = q.join(Author).where(Author.user == user) q = q.join(Author).where(Author.user == user)
q = q.group_by(Topic.id) return get_topics_with_stat(q)
topics = await get_with_stat(q, Author, TopicFollower)
return topics
@query.field('get_topic') @query.field('get_topic')
async def get_topic(_, _info, slug): def get_topic(_, _info, slug):
q = select(Topic).filter(Topic.slug == slug) q = select(Topic).filter(Topic.slug == slug)
q = q.group_by(Topic.id) q = q.group_by(Topic.id)
topics = await get_with_stat(q, Author, TopicFollower) topics = get_topics_with_stat(q)
if topics: if topics:
return topics[0] return topics[0]
@mutation.field('create_topic') @mutation.field('create_topic')
@login_required @login_required
async def create_topic(_, _info, inp): def create_topic(_, _info, inp):
with local_session() as session: with local_session() as session:
# TODO: check user permissions to create topic for exact community # TODO: check user permissions to create topic for exact community
# and actor is permitted to craete it # and actor is permitted to craete it
@ -65,7 +58,7 @@ async def create_topic(_, _info, inp):
@mutation.field('update_topic') @mutation.field('update_topic')
@login_required @login_required
async def update_topic(_, _info, inp): def update_topic(_, _info, inp):
slug = inp['slug'] slug = inp['slug']
with local_session() as session: with local_session() as session:
topic = session.query(Topic).filter(Topic.slug == slug).first() topic = session.query(Topic).filter(Topic.slug == slug).first()
@ -81,7 +74,7 @@ async def update_topic(_, _info, inp):
@mutation.field('delete_topic') @mutation.field('delete_topic')
@login_required @login_required
async def delete_topic(_, info, slug: str): def delete_topic(_, info, slug: str):
user_id = info.context['user_id'] user_id = info.context['user_id']
with local_session() as session: with local_session() as session:
t: Topic = session.query(Topic).filter(Topic.slug == slug).first() t: Topic = session.query(Topic).filter(Topic.slug == slug).first()