model changes

This commit is contained in:
Igor Lobanov 2022-11-29 13:36:46 +01:00
parent b840823fce
commit 226aeddecd
20 changed files with 254 additions and 166 deletions

1
.gitignore vendored
View File

@ -148,3 +148,4 @@ dump
*dump.sql
*.csv
dev-server-status.txt
/resetdb.sh

View File

@ -119,8 +119,7 @@ async def shouts_handle(storage, args):
# print main counter
counter += 1
line = str(counter + 1) + ": " + shout["slug"] + " @" + author["slug"]
print(line)
print('[migration] shouts_handle %d: %s @%s' % ((counter + 1), shout["slug"], author["slug"]))
b = bs4.BeautifulSoup(shout["body"], "html.parser")
texts = [shout["title"].lower().replace(r"[^а-яА-Яa-zA-Z]", "")]

View File

@ -5,8 +5,8 @@ from dateutil.parser import parse as date_parse
from base.orm import local_session
from migration.html2text import html2text
from orm.reaction import Reaction, ReactionKind
from orm.shout import ShoutReactionsFollower
from orm.topic import TopicFollower
from orm.shout import ShoutReactionsFollower, Shout
from orm.topic import TopicFollower, Topic
from orm.user import User
ts = datetime.now(tz=timezone.utc)
@ -69,8 +69,13 @@ async def migrate(entry, storage):
author = session.query(User).filter(User.oid == entry["createdBy"]).first()
shout_dict = storage["shouts"]["by_oid"][shout_oid]
if shout_dict:
reaction_dict["shout"] = shout_dict["slug"]
reaction_dict["createdBy"] = author.slug if author else "discours"
shout = session.query(
Shout
).where(Shout.slug == shout_dict["slug"]).one()
reaction_dict["shout_id"] = shout.id
reaction_dict["createdBy"] = author.id if author else 1
reaction_dict["kind"] = ReactionKind.COMMENT
# creating reaction from old comment
@ -80,15 +85,20 @@ async def migrate(entry, storage):
# creating shout's reactions following for reaction author
following1 = session.query(
ShoutReactionsFollower
).join(
User
).join(
Shout
).where(
ShoutReactionsFollower.follower == reaction_dict["createdBy"]
User.id == reaction_dict["createdBy"]
).filter(
ShoutReactionsFollower.shout == reaction.shout
ShoutReactionsFollower.shout_id == reaction.shout_id
).first()
if not following1:
following1 = ShoutReactionsFollower.create(
follower=reaction_dict["createdBy"],
shout=reaction.shout,
follower_id=reaction_dict["createdBy"],
shout_id=reaction.shout_id,
auto=True
)
session.add(following1)
@ -97,15 +107,22 @@ async def migrate(entry, storage):
for t in shout_dict["topics"]:
tf = session.query(
TopicFollower
).join(
Topic
).where(
TopicFollower.follower == reaction_dict["createdBy"]
TopicFollower.follower_id == reaction_dict["createdBy"]
).filter(
TopicFollower.topic == t
Topic.slug == t
).first()
if not tf:
topic = session.query(
Topic
).where(Topic.slug == t).one()
topic_following = TopicFollower.create(
follower=reaction_dict["createdBy"],
topic=t,
follower_id=reaction_dict["createdBy"],
topic_id=topic.id,
auto=True
)
session.add(topic_following)
@ -114,16 +131,16 @@ async def migrate(entry, storage):
for comment_rating_old in entry.get("ratings", []):
rater = (
session.query(User)
.filter(User.oid == comment_rating_old["createdBy"])
.first()
.filter(User.oid == comment_rating_old["createdBy"])
.first()
)
re_reaction_dict = {
"shout": reaction_dict["shout"],
"shout_id": reaction_dict["shout_id"],
"replyTo": reaction.id,
"kind": ReactionKind.LIKE
if comment_rating_old["value"] > 0
else ReactionKind.DISLIKE,
"createdBy": rater.slug if rater else "discours",
"createdBy": rater.id if rater else 1,
}
cts = comment_rating_old.get("createdAt")
if cts:
@ -134,14 +151,14 @@ async def migrate(entry, storage):
following2 = session.query(
ShoutReactionsFollower
).where(
ShoutReactionsFollower.follower == re_reaction_dict['createdBy']
ShoutReactionsFollower.follower_id == re_reaction_dict['createdBy']
).filter(
ShoutReactionsFollower.shout == rr.shout
ShoutReactionsFollower.shout_id == rr.shout_id
).first()
if not following2:
following2 = ShoutReactionsFollower.create(
follower=re_reaction_dict['createdBy'],
shout=rr.shout,
follower_id=re_reaction_dict['createdBy'],
shout_id=rr.shout_id,
auto=True
)
session.add(following2)
@ -163,22 +180,26 @@ def migrate_2stage(rr, old_new_id):
reply_oid = rr.get("replyTo")
if not reply_oid:
return
new_id = old_new_id.get(rr.get("oid"))
if not new_id:
return
with local_session() as session:
comment = session.query(Reaction).filter(Reaction.id == new_id).first()
comment.replyTo = old_new_id.get(reply_oid)
session.add(comment)
srf = session.query(ShoutReactionsFollower).where(
ShoutReactionsFollower.shout == comment.shout
ShoutReactionsFollower.shout_id == comment.shout_id
).filter(
ShoutReactionsFollower.follower == comment.createdBy
ShoutReactionsFollower.follower_id == comment.createdBy
).first()
if not srf:
srf = ShoutReactionsFollower.create(shout=comment.shout, follower=comment.createdBy, auto=True)
srf = ShoutReactionsFollower.create(shout_id=comment.shout_id, follower_id=comment.createdBy, auto=True)
session.add(srf)
session.commit()
if not rr["body"]:
raise Exception(rr)

View File

@ -8,7 +8,7 @@ from migration.extract import extract_html, extract_media
from orm.reaction import Reaction, ReactionKind
from orm.shout import Shout, ShoutTopic, ShoutReactionsFollower
from orm.user import User
from orm.topic import TopicFollower
from orm.topic import TopicFollower, Topic
from services.stat.viewed import ViewedStorage
OLD_DATE = "2016-03-05 22:22:00.350000"
@ -41,10 +41,10 @@ def create_author_from_app(app):
name = app.get('name')
slug = (
translit(name, "ru", reversed=True)
.replace(" ", "-")
.replace("'", "")
.replace(".", "-")
.lower()
.replace(" ", "-")
.replace("'", "")
.replace(".", "-")
.lower()
)
# check if nameslug is used
user = session.query(User).where(User.slug == slug).first()
@ -84,13 +84,19 @@ def create_author_from_app(app):
async def create_shout(shout_dict, userslug):
s = Shout.create(**shout_dict)
with local_session() as session:
srf = session.query(ShoutReactionsFollower).where(
ShoutReactionsFollower.shout == s.slug
follower = session.query(User).where(User.slug == userslug).one()
srf = session.query(
ShoutReactionsFollower
).join(
User
).where(
ShoutReactionsFollower.shout_id == s.id
).filter(
ShoutReactionsFollower.follower == userslug
User.slug == userslug
).first()
if not srf:
srf = ShoutReactionsFollower.create(shout=s.slug, follower=userslug, auto=True)
srf = ShoutReactionsFollower.create(shout_id=s.id, follower_id=follower.id, auto=True)
session.add(srf)
session.commit()
@ -214,17 +220,21 @@ async def add_topics_follower(entry, storage, userslug):
with local_session() as session:
for tpc in topics:
try:
topic = session.query(Topic).where(Topic.slug == tpc).one()
follower = session.query(User).where(User.slug == userslug).one()
tf = session.query(
TopicFollower
).where(
TopicFollower.follower == userslug
TopicFollower.follower_id == follower.id
).filter(
TopicFollower.topic == tpc
TopicFollower.topic_id == topic.id
).first()
if not tf:
tf = TopicFollower.create(
topic=tpc,
follower=userslug,
topic_id=topic.id,
follower_id=follower.id,
auto=True
)
session.add(tf)
@ -300,27 +310,35 @@ async def topics_aftermath(entry, storage):
for tpc in filter(lambda x: bool(x), entry["topics"]):
oldslug = tpc
newslug = storage["replacements"].get(oldslug, oldslug)
if newslug:
with local_session() as session:
shout = session.query(Shout).where(Shout.slug == entry["slug"]).one()
new_topic = session.query(Topic).where(Topic.slug == newslug).one()
shout_topic_old = (
session.query(ShoutTopic)
.filter(ShoutTopic.shout == entry["slug"])
.filter(ShoutTopic.topic == oldslug)
.first()
.join(Shout)
.join(Topic)
.filter(Shout.slug == entry["slug"])
.filter(Topic.slug == oldslug)
.first()
)
if shout_topic_old:
shout_topic_old.update({"slug": newslug})
shout_topic_old.update({"topic_id": new_topic.id})
else:
shout_topic_new = (
session.query(ShoutTopic)
.filter(ShoutTopic.shout == entry["slug"])
.filter(ShoutTopic.topic == newslug)
.first()
.join(Shout)
.join(Topic)
.filter(Shout.slug == entry["slug"])
.filter(Topic.slug == newslug)
.first()
)
if not shout_topic_new:
try:
ShoutTopic.create(
**{"shout": entry["slug"], "topic": newslug}
**{"shout_id": shout.id, "topic_id": new_topic.id}
)
except Exception:
print("[migration] shout topic error: " + newslug)
@ -339,31 +357,35 @@ async def content_ratings_to_reactions(entry, slug):
for content_rating in entry.get("ratings", []):
rater = (
session.query(User)
.filter(User.oid == content_rating["createdBy"])
.first()
.filter(User.oid == content_rating["createdBy"])
.first()
)
reactedBy = (
rater
if rater
else session.query(User).filter(User.slug == "noname").first()
else session.query(User).filter(User.slug == "anonymous").first()
)
if rater:
shout = session.query(Shout).where(Shout.slug == slug).one()
reaction_dict = {
"kind": ReactionKind.LIKE
if content_rating["value"] > 0
else ReactionKind.DISLIKE,
"createdBy": reactedBy.slug,
"shout": slug,
"createdBy": reactedBy.id,
"shout_id": shout.id,
}
cts = content_rating.get("createdAt")
if cts:
reaction_dict["createdAt"] = date_parse(cts)
reaction = (
session.query(Reaction)
.filter(Reaction.shout == reaction_dict["shout"])
.filter(Reaction.createdBy == reaction_dict["createdBy"])
.filter(Reaction.kind == reaction_dict["kind"])
.first()
session.query(Reaction).filter(
Reaction.shout_id == reaction_dict["shout_id"]
).filter(
Reaction.createdBy == reaction_dict["createdBy"]
).filter(
Reaction.kind == reaction_dict["kind"]
).first()
)
if reaction:
k = ReactionKind.AGREE if content_rating["value"] > 0 else ReactionKind.DISAGREE

View File

@ -115,18 +115,23 @@ def migrate_2stage(entry, id_map):
continue
oid = entry["_id"]
author_slug = id_map.get(oid)
user_rating_dict = {
"value": rating_entry["value"],
"rater": rater_slug,
"user": author_slug,
}
with local_session() as session:
try:
rater = session.query(User).where(User.slug == rater_slug).one()
user = session.query(User).where(User.slug == author_slug).one()
user_rating_dict = {
"value": rating_entry["value"],
"rater_id": rater.id,
"user_id": user.id,
}
user_rating = UserRating.create(**user_rating_dict)
if user_rating_dict['value'] > 0:
af = AuthorFollower.create(
author=user_rating_dict['user'],
follower=user_rating_dict['rater'],
author_id=user.id,
follower_id=rater.id,
auto=True
)
session.add(af)

View File

@ -11,14 +11,13 @@ class CollabAuthor(Base):
id = None # type: ignore
collab = Column(ForeignKey("collab.id"), primary_key=True)
author = Column(ForeignKey("user.slug"), primary_key=True)
author_id = Column(ForeignKey("user.id"), primary_key=True)
accepted = Column(Boolean, default=False)
class Collab(Base):
__tablename__ = "collab"
authors = Column()
title = Column(String, nullable=True, comment="Title")
body = Column(String, nullable=True, comment="Body")
pic = Column(String, nullable=True, comment="Picture")

View File

@ -9,8 +9,8 @@ class ShoutCollection(Base):
__tablename__ = "shout_collection"
id = None # type: ignore
shout = Column(ForeignKey("shout.slug"), primary_key=True)
collection = Column(ForeignKey("collection.slug"), primary_key=True)
shout_id = Column(ForeignKey("shout.id"), primary_key=True)
collection_id = Column(ForeignKey("collection.id"), primary_key=True)
class Collection(Base):

View File

@ -8,8 +8,8 @@ class CommunityFollower(Base):
__tablename__ = "community_followers"
id = None # type: ignore
follower = Column(ForeignKey("user.slug"), primary_key=True)
community = Column(ForeignKey("community.slug"), primary_key=True)
follower_id = Column(ForeignKey("user.id"), primary_key=True)
community_id = Column(ForeignKey("community.id"), primary_key=True)
joinedAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at"
)

View File

@ -28,12 +28,12 @@ class Reaction(Base):
createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at"
)
createdBy = Column(ForeignKey("user.slug"), nullable=False, comment="Sender")
createdBy = Column(ForeignKey("user.id"), nullable=False, index=True, comment="Sender")
updatedAt = Column(DateTime, nullable=True, comment="Updated at")
updatedBy = Column(ForeignKey("user.slug"), nullable=True, comment="Last Editor")
updatedBy = Column(ForeignKey("user.id"), nullable=True, index=True, comment="Last Editor")
deletedAt = Column(DateTime, nullable=True, comment="Deleted at")
deletedBy = Column(ForeignKey("user.slug"), nullable=True, comment="Deleted by")
shout = Column(ForeignKey("shout.slug"), nullable=False)
deletedBy = Column(ForeignKey("user.id"), nullable=True, index=True, comment="Deleted by")
shout_id = Column(ForeignKey("shout.id"), nullable=False, index=True)
replyTo = Column(
ForeignKey("reaction.id"), nullable=True, comment="Reply to reaction ID"
)

View File

@ -13,16 +13,16 @@ class ShoutTopic(Base):
__tablename__ = "shout_topic"
id = None # type: ignore
shout = Column(ForeignKey("shout.slug"), primary_key=True)
topic = Column(ForeignKey("topic.slug"), primary_key=True)
shout_id = Column(ForeignKey("shout.id"), primary_key=True, index=True)
topic_id = Column(ForeignKey("topic.id"), primary_key=True, index=True)
class ShoutReactionsFollower(Base):
__tablename__ = "shout_reactions_followers"
id = None # type: ignore
follower = Column(ForeignKey("user.slug"), primary_key=True)
shout = Column(ForeignKey("shout.slug"), primary_key=True)
follower_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
shout_id = Column(ForeignKey("shout.id"), primary_key=True, index=True)
auto = Column(Boolean, nullable=False, default=False)
createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at"
@ -34,8 +34,8 @@ class ShoutAuthor(Base):
__tablename__ = "shout_author"
id = None # type: ignore
shout = Column(ForeignKey("shout.slug"), primary_key=True)
user = Column(ForeignKey("user.slug"), primary_key=True)
shout_id = Column(ForeignKey("shout.id"), primary_key=True, index=True)
user_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
caption = Column(String, nullable=True, default="")
@ -55,7 +55,7 @@ class Shout(Base):
topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__)
reactions = relationship(lambda: Reaction)
visibility = Column(String, nullable=True) # owner authors community public
versionOf = Column(ForeignKey("shout.slug"), nullable=True)
versionOf = Column(ForeignKey("shout.id"), nullable=True)
oid = Column(String, nullable=True)
media = Column(JSON, nullable=True)

View File

@ -9,8 +9,8 @@ class TopicFollower(Base):
__tablename__ = "topic_followers"
id = None # type: ignore
follower = Column(ForeignKey("user.slug"), primary_key=True)
topic = Column(ForeignKey("topic.slug"), primary_key=True)
follower_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
topic_id = Column(ForeignKey("topic.id"), primary_key=True, index=True)
createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at"
)

View File

@ -6,7 +6,6 @@ from sqlalchemy.orm import relationship
from base.orm import Base, local_session
from orm.rbac import Role
from services.auth.roles import RoleStorage
class UserNotifications(Base):
@ -21,8 +20,8 @@ class UserRating(Base):
__tablename__ = "user_rating"
id = None # type: ignore
rater = Column(ForeignKey("user.slug"), primary_key=True)
user = Column(ForeignKey("user.slug"), primary_key=True)
rater_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
user_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
value = Column(Integer)
@staticmethod
@ -34,16 +33,16 @@ class UserRole(Base):
__tablename__ = "user_role"
id = None # type: ignore
user_id = Column(ForeignKey("user.id"), primary_key=True)
role_id = Column(ForeignKey("role.id"), primary_key=True)
user_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
role_id = Column(ForeignKey("role.id"), primary_key=True, index=True)
class AuthorFollower(Base):
__tablename__ = "author_follower"
id = None # type: ignore
follower = Column(ForeignKey("user.slug"), primary_key=True)
author = Column(ForeignKey("user.slug"), primary_key=True)
follower_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
author_id = Column(ForeignKey("user.id"), primary_key=True, index=True)
createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at"
)
@ -73,7 +72,7 @@ class User(Base):
links = Column(JSONType, nullable=True, comment="Links")
oauth = Column(String, nullable=True)
notifications = relationship(lambda: UserNotifications)
ratings = relationship(UserRating, foreign_keys=UserRating.user)
ratings = relationship(UserRating, foreign_keys=UserRating.user_id)
roles = relationship(lambda: Role, secondary=UserRole.__tablename__)
oid = Column(String, nullable=True)

View File

@ -6,8 +6,8 @@ from base.orm import Base, local_session
class ViewedEntry(Base):
__tablename__ = "viewed"
viewer = Column(ForeignKey("user.slug"), default='anonymous')
shout = Column(ForeignKey("shout.slug"), default="genesis-block")
viewer_id = Column(ForeignKey("user.id"), index=True, default=1)
shout_id = Column(ForeignKey("shout.id"), index=True, default=1)
amount = Column(Integer, default=1)
createdAt = Column(
DateTime, nullable=False, default=datetime.now, comment="Created at"

View File

@ -1,11 +1,13 @@
from datetime import datetime, timezone
from sqlalchemy import and_
from auth.authenticate import login_required
from base.orm import local_session
from base.resolvers import mutation
from orm.rbac import Resource
from orm.shout import Shout, ShoutAuthor, ShoutTopic
from orm.topic import TopicFollower
from orm.topic import TopicFollower, Topic
from orm.user import User
from resolvers.zine.reactions import reactions_follow, reactions_unfollow
from services.zine.gittask import GitTask
@ -24,7 +26,7 @@ async def create_shout(_, info, inp):
new_shout = Shout.create(**inp)
# NOTE: shout made by one first author
sa = ShoutAuthor.create(shout=new_shout.slug, user=user.slug)
sa = ShoutAuthor.create(shout_id=new_shout.id, user_id=user.id)
session.add(sa)
reactions_follow(user, new_shout.slug, True)
@ -33,11 +35,16 @@ async def create_shout(_, info, inp):
topic_slugs.append(inp["mainTopic"])
for slug in topic_slugs:
st = ShoutTopic.create(shout=new_shout.slug, topic=slug)
topic = session.query(Topic).where(Topic.slug == slug).one()
st = ShoutTopic.create(shout_id=new_shout.id, topic_id=topic.id)
session.add(st)
tf = session.query(TopicFollower).where(follower=user.slug, topic=slug)
tf = session.query(TopicFollower).where(
and_(TopicFollower.follower_id == user.id, TopicFollower.topic_id == topic.id)
)
if not tf:
tf = TopicFollower.create(follower=user.slug, topic=slug, auto=True)
tf = TopicFollower.create(follower_id=user.id, topic_id=topic.id, auto=True)
session.add(tf)
new_shout.topic_slugs = topic_slugs
@ -45,7 +52,7 @@ async def create_shout(_, info, inp):
session.commit()
GitTask(inp, user.username, user.email, "new shout %s" % (new_shout.slug))
GitTask(inp, user.username, user.email, "new shout %s" % new_shout.slug)
return {"shout": new_shout}
@ -75,7 +82,7 @@ async def update_shout(_, info, inp):
session.add(shout)
if inp.get("topics"):
# remove old links
links = session.query(ShoutTopic).where(ShoutTopic.shout == slug).all()
links = session.query(ShoutTopic).where(ShoutTopic.shout_id == shout.id).all()
for topiclink in links:
session.delete(topiclink)
# add new topic links

View File

@ -4,7 +4,7 @@ from auth.authenticate import login_required
from base.redis import redis
from base.resolvers import query
from base.orm import local_session
from orm.user import AuthorFollower
from orm.user import AuthorFollower, User
@query.field("searchRecipients")
@ -30,13 +30,19 @@ async def search_recipients(_, info, query: str, limit: int = 50, offset: int =
with local_session() as session:
# followings
result += session.query(AuthorFollower.author).where(AuthorFollower.follower.startswith(query))\
.offset(offset + len(result)).limit(more_amount)
result += session.query(AuthorFollower.author).join(
User, User.id == AuthorFollower.follower_id
).where(
User.slug.startswith(query)
).offset(offset + len(result)).limit(more_amount)
more_amount = limit
# followers
result += session.query(AuthorFollower.follower).where(AuthorFollower.author.startswith(query))\
.offset(offset + len(result)).limit(offset + len(result) + limit)
result += session.query(AuthorFollower.follower).join(
User, User.id == AuthorFollower.author_id
).where(
User.slug.startswith(query)
).offset(offset + len(result)).limit(offset + len(result) + limit)
return {
"members": list(result),
"error": None

View File

@ -1,11 +1,11 @@
from datetime import datetime, timedelta, timezone
from sqlalchemy.orm import joinedload, aliased
from sqlalchemy.sql.expression import desc, asc, select, case, func
from sqlalchemy.sql.expression import desc, asc, select, func
from base.orm import local_session
from base.resolvers import query
from orm import ViewedEntry
from orm.shout import Shout, ShoutAuthor
from orm.reaction import Reaction, ReactionKind
from orm.reaction import Reaction
from resolvers.zine._common import add_common_stat_columns
@ -18,7 +18,7 @@ def add_stat_columns(q):
def apply_filters(q, filters, user=None):
if filters.get("reacted") and user:
q.join(Reaction, Reaction.createdBy == user.slug)
q.join(Reaction, Reaction.createdBy == user.id)
v = filters.get("visibility")
if v == "public":
@ -66,9 +66,9 @@ async def load_shout(_, info, slug):
"rating": rating_stat
}
for author_caption in session.query(ShoutAuthor).where(ShoutAuthor.shout == slug):
for author_caption in session.query(ShoutAuthor).join(Shout).where(Shout.slug == slug):
for author in shout.authors:
if author.slug == author_caption.user:
if author.id == author_caption.user_id:
author.caption = author_caption.caption
return shout

View File

@ -19,17 +19,19 @@ from resolvers.zine.topics import followed_by_user
def add_author_stat_columns(q):
author_followers = aliased(AuthorFollower)
author_following = aliased(AuthorFollower)
shout_author_aliased = aliased(ShoutAuthor)
user_rating_aliased = aliased(UserRating)
q = q.outerjoin(ShoutAuthor).add_columns(
func.count(distinct(ShoutAuthor.shout)).label('shouts_stat')
).outerjoin(author_followers, author_followers.author == User.slug).add_columns(
func.count(distinct(author_followers.follower)).label('followers_stat')
).outerjoin(author_following, author_following.follower == User.slug).add_columns(
func.count(distinct(author_following.author)).label('followings_stat')
).outerjoin(UserRating).add_columns(
q = q.outerjoin(shout_author_aliased).add_columns(
func.count(distinct(shout_author_aliased.shout_id)).label('shouts_stat')
).outerjoin(author_followers, author_followers.author_id == User.id).add_columns(
func.count(distinct(author_followers.follower_id)).label('followers_stat')
).outerjoin(author_following, author_following.follower_id == User.id).add_columns(
func.count(distinct(author_following.author_id)).label('followings_stat')
).outerjoin(user_rating_aliased, user_rating_aliased.user_id == User.id).add_columns(
# TODO: check
func.sum(UserRating.value).label('rating_stat')
).outerjoin(Reaction, and_(Reaction.createdBy == User.slug, Reaction.body.is_not(None))).add_columns(
func.sum(user_rating_aliased.value).label('rating_stat')
).outerjoin(Reaction, and_(Reaction.createdBy == User.id, Reaction.body.is_not(None))).add_columns(
func.count(distinct(Reaction.id)).label('commented_stat')
)
@ -83,7 +85,7 @@ async def followed_reactions(slug):
return session.query(
Reaction.shout
).where(
Reaction.createdBy == slug
Reaction.createdBy == user.id
).filter(
Reaction.createdAt > user.lastSeen
).all()
@ -107,7 +109,7 @@ async def get_followed_authors(_, _info, slug) -> List[User]:
async def followed_authors(slug) -> List[User]:
q = select(User)
q = add_author_stat_columns(q)
q = q.join(AuthorFollower).where(AuthorFollower.follower == slug)
q = q.join(AuthorFollower).join(User, User.id == AuthorFollower.follower_id).where(User.slug == slug)
return get_authors_from_query(q)
@ -116,7 +118,13 @@ async def followed_authors(slug) -> List[User]:
async def user_followers(_, _info, slug) -> List[User]:
q = select(User)
q = add_author_stat_columns(q)
q = q.join(AuthorFollower).where(AuthorFollower.author == slug)
aliased_user = aliased(User)
q = q.join(AuthorFollower).join(
aliased_user, aliased_user.id == AuthorFollower.author_id
).where(
aliased_user.slug == slug
)
return get_authors_from_query(q)
@ -173,7 +181,8 @@ async def rate_user(_, info, rated_userslug, value):
# for mutation.field("follow")
def author_follow(user, slug):
with local_session() as session:
af = AuthorFollower.create(follower=user.slug, author=slug)
author = session.query(User).where(User.slug == slug).one()
af = AuthorFollower.create(follower_id=user.id, author_id=author.id)
session.add(af)
session.commit()
@ -182,13 +191,13 @@ def author_follow(user, slug):
def author_unfollow(user, slug):
with local_session() as session:
flw = (
session.query(AuthorFollower)
.filter(
session.query(
AuthorFollower
).join(User, User.id == AuthorFollower.author_id).filter(
and_(
AuthorFollower.follower == user.slug, AuthorFollower.author == slug
AuthorFollower.follower_id == user.id, User.slug == slug
)
)
.first()
).first()
)
if not flw:
raise Exception("[resolvers.profile] follower not exist, cant unfollow")
@ -224,7 +233,7 @@ async def load_authors_by(_, info, by, limit, offset):
elif by.get("name"):
q = q.filter(User.name.ilike(f"%{by['name']}%"))
elif by.get("topic"):
q = q.join(ShoutAuthor).join(ShoutTopic).where(ShoutTopic.topic == by["topic"])
q = q.join(ShoutAuthor).join(ShoutTopic).join(Topic).where(Topic.slug == by["topic"])
if by.get("lastSeen"): # in days
days_before = datetime.now(tz=timezone.utc) - timedelta(days=by["lastSeen"])
q = q.filter(User.lastSeen > days_before)

View File

@ -16,16 +16,19 @@ def add_reaction_stat_columns(q):
def reactions_follow(user: User, slug: str, auto=False):
with local_session() as session:
shout = session.query(Shout).where(Shout.slug == slug).one()
following = (
session.query(ShoutReactionsFollower).where(and_(
ShoutReactionsFollower.follower == user.slug,
ShoutReactionsFollower.shout == slug
ShoutReactionsFollower.follower_id == user.id,
ShoutReactionsFollower.shout_id == shout.id,
)).first()
)
if not following:
following = ShoutReactionsFollower.create(
follower=user.slug,
shout=slug,
follower_id=user.id,
shout_id=shout.id,
auto=auto
)
session.add(following)
@ -34,12 +37,15 @@ def reactions_follow(user: User, slug: str, auto=False):
def reactions_unfollow(user, slug):
with local_session() as session:
shout = session.query(Shout).where(Shout.slug == slug).one()
following = (
session.query(ShoutReactionsFollower).where(and_(
ShoutReactionsFollower.follower == user.slug,
ShoutReactionsFollower.shout == slug
ShoutReactionsFollower.follower_id == user.id,
ShoutReactionsFollower.shout_id == shout.id
)).first()
)
if following:
session.delete(following)
session.commit()
@ -68,7 +74,7 @@ def check_to_publish(session, user, reaction):
]:
if is_published_author(user):
# now count how many approvers are voted already
approvers_reactions = session.query(Reaction).where(Reaction.shout == reaction.shout).all()
approvers_reactions = session.query(Reaction).where(Reaction.shout_id == reaction.shout_id).all()
approvers = [user.slug, ]
for ar in approvers_reactions:
a = ar.createdBy
@ -87,7 +93,7 @@ def check_to_hide(session, user, reaction):
ReactionKind.UNPROOF
]:
# if is_published_author(user):
approvers_reactions = session.query(Reaction).where(Reaction.shout == reaction.shout).all()
approvers_reactions = session.query(Reaction).where(Reaction.shout_id == reaction.shout_id).all()
declines = 0
for r in approvers_reactions:
if r.kind in [
@ -224,22 +230,26 @@ async def load_reactions_by(_, _info, by, limit=50, offset=0):
q = select(
Reaction, CreatedByUser, ReactedShout
).join(
CreatedByUser, Reaction.createdBy == CreatedByUser.slug
CreatedByUser, Reaction.createdBy == CreatedByUser.id
).join(
ReactedShout, Reaction.shout == ReactedShout.slug
ReactedShout, Reaction.shout_id == ReactedShout.id
)
if by.get("shout"):
q = q.filter(Reaction.shout == by["shout"])
aliased_shout = aliased(Shout)
q = q.join(aliased_shout).filter(aliased_shout.slug == by["shout"])
elif by.get("shouts"):
q = q.filter(Reaction.shout.in_(by["shouts"]))
aliased_shout = aliased(Shout)
q = q.join(aliased_shout).filter(aliased_shout.shout.in_(by["shouts"]))
if by.get("createdBy"):
q = q.filter(Reaction.createdBy == by.get("createdBy"))
aliased_user = aliased(User)
q = q.join(aliased_user).filter(aliased_user.slug == by.get("createdBy"))
if by.get("topic"):
# TODO: check
q = q.filter(Shout.topics.contains(by["topic"]))
if by.get("comment"):
q = q.filter(func.length(Reaction.body) > 0)
if by.get('search', 0) > 2:
if len(by.get('search', '')) > 2:
q = q.filter(Reaction.body.ilike(f'%{by["body"]}%'))
if by.get("days"):
after = datetime.now(tz=timezone.utc) - timedelta(days=int(by["days"]) or 30)

View File

@ -4,20 +4,20 @@ from base.orm import local_session
from base.resolvers import mutation, query
from orm.shout import ShoutTopic, ShoutAuthor
from orm.topic import Topic, TopicFollower
from orm import Shout
from orm import Shout, User
def add_topic_stat_columns(q):
q = q.outerjoin(ShoutTopic, Topic.slug == ShoutTopic.topic).add_columns(
func.count(distinct(ShoutTopic.shout)).label('shouts_stat')
).outerjoin(ShoutAuthor, ShoutTopic.shout == ShoutAuthor.shout).add_columns(
func.count(distinct(ShoutAuthor.user)).label('authors_stat')
q = q.outerjoin(ShoutTopic, Topic.id == ShoutTopic.topic_id).add_columns(
func.count(distinct(ShoutTopic.shout_id)).label('shouts_stat')
).outerjoin(ShoutAuthor, ShoutTopic.shout_id == ShoutAuthor.shout_id).add_columns(
func.count(distinct(ShoutAuthor.user_id)).label('authors_stat')
).outerjoin(TopicFollower,
and_(
TopicFollower.topic == Topic.slug,
TopicFollower.follower == ShoutAuthor.user
TopicFollower.topic_id == Topic.id,
TopicFollower.follower_id == ShoutAuthor.id
)).add_columns(
func.count(distinct(TopicFollower.follower)).label('followers_stat')
func.count(distinct(TopicFollower.follower_id)).label('followers_stat')
)
q = q.group_by(Topic.id)
@ -49,7 +49,7 @@ def get_topics_from_query(q):
def followed_by_user(user_slug):
q = select(Topic)
q = add_topic_stat_columns(q)
q = q.where(TopicFollower.follower == user_slug)
q = q.join(User).where(User.slug == user_slug)
return get_topics_from_query(q)
@ -74,7 +74,7 @@ async def topics_by_community(_, info, community):
async def topics_by_author(_, _info, author):
q = select(Topic)
q = add_topic_stat_columns(q)
q = q.where(ShoutAuthor.user == author)
q = q.join(User).where(User.slug == author)
return get_topics_from_query(q)
@ -117,7 +117,9 @@ async def update_topic(_, _info, inp):
async def topic_follow(user, slug):
with local_session() as session:
following = TopicFollower.create(topic=slug, follower=user.slug)
topic = session.query(Topic).where(Topic.slug == slug).one()
following = TopicFollower.create(topic_id=topic.id, follower=user.id)
session.add(following)
session.commit()
@ -125,10 +127,10 @@ async def topic_follow(user, slug):
async def topic_unfollow(user, slug):
with local_session() as session:
sub = (
session.query(TopicFollower).filter(
session.query(TopicFollower).join(Topic).filter(
and_(
TopicFollower.follower == user.slug,
TopicFollower.topic == slug
TopicFollower.follower_id == user.id,
Topic.slug == slug
)
).first()
)
@ -143,7 +145,7 @@ async def topic_unfollow(user, slug):
async def topics_random(_, info, amount=12):
q = select(Topic)
q = add_topic_stat_columns(q)
q = q.join(Shout, ShoutTopic.shout == Shout.slug).group_by(Topic.id).having(func.count(Shout.id) > 2)
q = q.join(Shout, ShoutTopic.shout_id == Shout.id).group_by(Topic.id).having(func.count(Shout.id) > 2)
q = q.order_by(func.random()).limit(amount)
return get_topics_from_query(q)

View File

@ -5,7 +5,9 @@ from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport
from base.orm import local_session
from sqlalchemy import func
from orm.shout import ShoutTopic
from orm import User, Topic
from orm.shout import ShoutTopic, Shout
from orm.viewed import ViewedEntry
from ssl import create_default_context
from os import environ, path
@ -113,6 +115,7 @@ class ViewedStorage:
async with self.lock:
return self.client.execute_async(load_facts)
# unused yet
@staticmethod
async def get_shout(shout_slug):
""" getting shout views metric by slug """
@ -123,8 +126,9 @@ class ViewedStorage:
shout_views = 0
with local_session() as session:
try:
shout = session.query(Shout).where(Shout.slug == shout_slug).one()
shout_views = session.query(func.sum(ViewedEntry.amount)).where(
ViewedEntry.shout == shout_slug
ViewedEntry.shout_id == shout.id
).all()[0][0]
self.by_shouts[shout_slug] = shout_views
self.update_topics(session, shout_slug)
@ -147,11 +151,12 @@ class ViewedStorage:
def update_topics(session, shout_slug):
""" updates topics counters by shout slug """
self = ViewedStorage
for t in session.query(ShoutTopic).where(ShoutTopic.shout == shout_slug).all():
tpc = t.topic
if not self.by_topics.get(tpc):
self.by_topics[tpc] = {}
self.by_topics[tpc][shout_slug] = self.by_shouts[shout_slug]
for [shout_topic, topic] in session.query(ShoutTopic, Topic).join(Topic).join(Shout).where(
Shout.slug == shout_slug
).all():
if not self.by_topics.get(topic.slug):
self.by_topics[topic.slug] = {}
self.by_topics[topic.slug][shout_slug] = self.by_shouts[shout_slug]
@staticmethod
async def increment(shout_slug, amount=1, viewer='anonymous'):
@ -159,9 +164,12 @@ class ViewedStorage:
self = ViewedStorage
async with self.lock:
with local_session() as session:
shout = session.query(Shout).where(Shout.slug == shout_slug).one()
viewer = session.query(User).where(User.slug == viewer).one()
viewed = ViewedEntry.create(**{
"viewer": viewer,
"shout": shout_slug,
"viewer_id": viewer.id,
"shout_id": shout.id,
"amount": amount
})
session.add(viewed)