random topic shouts query, published date filter in random tops (#113)

Co-authored-by: Igor Lobanov <igor.lobanov@onetwotrip.com>
This commit is contained in:
Igor Lobanov 2023-12-21 00:53:53 +01:00 committed by GitHub
parent ff834987d4
commit f395832d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 8 deletions

View File

@ -22,6 +22,7 @@ from orm import TopicFollower
from orm.reaction import Reaction, ReactionKind from orm.reaction import Reaction, ReactionKind
from orm.shout import Shout, ShoutAuthor, ShoutTopic from orm.shout import Shout, ShoutAuthor, ShoutTopic
from orm.user import AuthorFollower from orm.user import AuthorFollower
from resolvers.zine.topics import get_random_topic
def get_shouts_from_query(q): def get_shouts_from_query(q):
@ -79,7 +80,8 @@ def add_stat_columns(q):
return q return q
def apply_filters(q, filters, user_id=None): # noqa: C901 # use_published_date is a quick fix, will be reworked as a part of tech debt
def apply_filters(q, filters, user_id=None, use_published_date=False): # noqa: C901
if filters.get("reacted") and user_id: if filters.get("reacted") and user_id:
q.join(Reaction, Reaction.createdBy == user_id) q.join(Reaction, Reaction.createdBy == user_id)
@ -100,12 +102,17 @@ def apply_filters(q, filters, user_id=None): # noqa: C901
if filters.get("fromDate"): if filters.get("fromDate"):
# fromDate: '2022-12-31 # fromDate: '2022-12-31
date_from = datetime.strptime(filters.get("fromDate"), "%Y-%m-%d") date_from = datetime.strptime(filters.get("fromDate"), "%Y-%m-%d")
q = q.filter(Shout.createdAt >= date_from) if use_published_date:
q = q.filter(Shout.publishedAt >= date_from)
else:
q = q.filter(Shout.createdAt >= date_from)
if filters.get("toDate"): if filters.get("toDate"):
# toDate: '2023-12-31' # toDate: '2023-12-31'
date_to = datetime.strptime(filters.get("toDate"), "%Y-%m-%d") date_to = datetime.strptime(filters.get("toDate"), "%Y-%m-%d")
q = q.filter(Shout.createdAt < (date_to + timedelta(days=1))) if use_published_date:
q = q.filter(Shout.publishedAt < (date_to + timedelta(days=1)))
else:
q = q.filter(Shout.createdAt < (date_to + timedelta(days=1)))
return q return q
@ -228,7 +235,8 @@ async def load_random_top_shouts(_, info, params):
.where(and_(Shout.deletedAt.is_(None), Shout.layout.is_not(None))) .where(and_(Shout.deletedAt.is_(None), Shout.layout.is_not(None)))
) )
subquery = apply_filters(subquery, params.get("filters", {})) subquery = apply_filters(subquery, params.get("filters", {}), use_published_date=True)
subquery = subquery.group_by(Shout.id).order_by(desc(get_rating_func(aliased_reaction))) subquery = subquery.group_by(Shout.id).order_by(desc(get_rating_func(aliased_reaction)))
from_random_count = params.get("fromRandomCount") from_random_count = params.get("fromRandomCount")
@ -254,6 +262,29 @@ async def load_random_top_shouts(_, info, params):
return get_shouts_from_query(q) return get_shouts_from_query(q)
@query.field("loadRandomTopicShouts")
async def load_random_topic_shouts(_, info, limit):
topic = get_random_topic()
q = (
select(Shout)
.options(
joinedload(Shout.authors),
joinedload(Shout.topics),
)
.join(ShoutTopic, and_(Shout.id == ShoutTopic.shout, ShoutTopic.topic == topic.id))
.where(and_(Shout.deletedAt.is_(None), Shout.layout.is_not(None)))
)
q = add_stat_columns(q)
q = q.group_by(Shout.id).order_by(desc(Shout.createdAt)).limit(limit)
shouts = get_shouts_from_query(q)
return {"topic": topic, "shouts": shouts}
@query.field("loadUnratedShouts") @query.field("loadUnratedShouts")
async def load_unrated_shouts(_, info, limit): async def load_unrated_shouts(_, info, limit):
auth: AuthCredentials = info.context["request"].auth auth: AuthCredentials = info.context["request"].auth

View File

@ -12,11 +12,12 @@ from orm.topic import Topic, TopicFollower
def add_topic_stat_columns(q): def add_topic_stat_columns(q):
aliased_shout_author = aliased(ShoutAuthor) aliased_shout_author = aliased(ShoutAuthor)
aliased_topic_follower = aliased(TopicFollower) aliased_topic_follower = aliased(TopicFollower)
aliased_shout_topic = aliased(ShoutTopic)
q = ( q = (
q.outerjoin(ShoutTopic, Topic.id == ShoutTopic.topic) q.outerjoin(aliased_shout_topic, Topic.id == aliased_shout_topic.topic)
.add_columns(func.count(distinct(ShoutTopic.shout)).label("shouts_stat")) .add_columns(func.count(distinct(aliased_shout_topic.shout)).label("shouts_stat"))
.outerjoin(aliased_shout_author, ShoutTopic.shout == aliased_shout_author.shout) .outerjoin(aliased_shout_author, aliased_shout_topic.shout == aliased_shout_author.shout)
.add_columns(func.count(distinct(aliased_shout_author.user)).label("authors_stat")) .add_columns(func.count(distinct(aliased_shout_author.user)).label("authors_stat"))
.outerjoin(aliased_topic_follower) .outerjoin(aliased_topic_follower)
.add_columns(func.count(distinct(aliased_topic_follower.follower)).label("followers_stat")) .add_columns(func.count(distinct(aliased_topic_follower.follower)).label("followers_stat"))
@ -146,6 +147,18 @@ def topic_unfollow(user_id, slug):
return False return False
def get_random_topic():
q = select(Topic)
q = q.join(ShoutTopic)
q = q.group_by(Topic.id)
q = q.having(func.count(distinct(ShoutTopic.shout)) > 10)
q = q.order_by(func.random()).limit(1)
with local_session() as session:
[topic] = session.execute(q).first()
return topic
@query.field("topicsRandom") @query.field("topicsRandom")
async def topics_random(_, info, amount=12): async def topics_random(_, info, amount=12):
q = select(Topic) q = select(Topic)

View File

@ -264,6 +264,11 @@ type MySubscriptionsQueryResult {
authors: [Author]! authors: [Author]!
} }
type RandomTopicShoutsQueryResult {
topic: Topic!
shouts: [Shout]!
}
type Query { type Query {
# inbox # inbox
loadChats( limit: Int, offset: Int): Result! # your chats loadChats( limit: Int, offset: Int): Result! # your chats
@ -282,6 +287,7 @@ type Query {
loadShout(slug: String, shout_id: Int): Shout loadShout(slug: String, shout_id: Int): Shout
loadShouts(options: LoadShoutsOptions): [Shout]! loadShouts(options: LoadShoutsOptions): [Shout]!
loadRandomTopShouts(params: LoadRandomTopShoutsParams): [Shout]! loadRandomTopShouts(params: LoadRandomTopShoutsParams): [Shout]!
loadRandomTopicShouts(limit: Int!): RandomTopicShoutsQueryResult!
loadUnratedShouts(limit: Int!): [Shout]! loadUnratedShouts(limit: Int!): [Shout]!
loadDrafts: [Shout]! loadDrafts: [Shout]!
loadReactionsBy(by: ReactionBy!, limit: Int, offset: Int): [Reaction]! loadReactionsBy(by: ReactionBy!, limit: Int, offset: Int): [Reaction]!