From 6d8f93d8a1169fe951935d31568b2bde15b56eeb Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 3 Dec 2020 13:39:56 -0500 Subject: [PATCH] More user aggregates. --- lemmy_api/src/site.rs | 2 +- lemmy_db/src/aggregates/mod.rs | 2 + .../src/{ => aggregates}/site_aggregates.rs | 0 lemmy_db/src/aggregates/user_aggregates.rs | 22 +++++++++ lemmy_db/src/lib.rs | 2 +- lemmy_db/src/views/site_view.rs | 8 ++-- lemmy_db/src/views/user_view.rs | 48 +++++++++++-------- lemmy_structs/src/site.rs | 2 +- .../up.sql | 19 ++++++-- 9 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 lemmy_db/src/aggregates/mod.rs rename lemmy_db/src/{ => aggregates}/site_aggregates.rs (100%) create mode 100644 lemmy_db/src/aggregates/user_aggregates.rs diff --git a/lemmy_api/src/site.rs b/lemmy_api/src/site.rs index 2cd97f7f6..c62224170 100644 --- a/lemmy_api/src/site.rs +++ b/lemmy_api/src/site.rs @@ -10,6 +10,7 @@ use actix_web::web::Data; use anyhow::Context; use lemmy_apub::fetcher::search_by_apub_id; use lemmy_db::{ + aggregates::site_aggregates::SiteAggregates, category::*, comment_view::*, community_view::*, @@ -19,7 +20,6 @@ use lemmy_db::{ naive_now, post_view::*, site::*, - site_aggregates::SiteAggregates, user_view::*, views::site_view::SiteView, Crud, diff --git a/lemmy_db/src/aggregates/mod.rs b/lemmy_db/src/aggregates/mod.rs new file mode 100644 index 000000000..2791c977d --- /dev/null +++ b/lemmy_db/src/aggregates/mod.rs @@ -0,0 +1,2 @@ +pub mod site_aggregates; +pub mod user_aggregates; diff --git a/lemmy_db/src/site_aggregates.rs b/lemmy_db/src/aggregates/site_aggregates.rs similarity index 100% rename from lemmy_db/src/site_aggregates.rs rename to lemmy_db/src/aggregates/site_aggregates.rs diff --git a/lemmy_db/src/aggregates/user_aggregates.rs b/lemmy_db/src/aggregates/user_aggregates.rs new file mode 100644 index 000000000..26c2c067c --- /dev/null +++ b/lemmy_db/src/aggregates/user_aggregates.rs @@ -0,0 +1,22 @@ +use crate::schema::user_aggregates; +use diesel::{result::Error, *}; +use serde::Serialize; + +#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)] +#[table_name = "user_aggregates"] +pub struct UserAggregates { + pub id: i32, + pub user_id: i32, + pub post_count: i64, + pub post_score: i64, + pub comment_count: i64, + pub comment_score: i64, +} + +impl UserAggregates { + pub fn read(conn: &PgConnection, id: i32) -> Result { + user_aggregates::table.find(id).first::(conn) + } +} + +// TODO add unit tests, to make sure triggers are working diff --git a/lemmy_db/src/lib.rs b/lemmy_db/src/lib.rs index c7f4585fd..a4600ac4e 100644 --- a/lemmy_db/src/lib.rs +++ b/lemmy_db/src/lib.rs @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize}; use std::{env, env::VarError}; pub mod activity; +pub mod aggregates; pub mod category; pub mod comment; pub mod comment_report; @@ -28,7 +29,6 @@ pub mod private_message; pub mod private_message_view; pub mod schema; pub mod site; -pub mod site_aggregates; pub mod user; pub mod user_mention; pub mod user_mention_view; diff --git a/lemmy_db/src/views/site_view.rs b/lemmy_db/src/views/site_view.rs index 9b14056ed..547c13b4b 100644 --- a/lemmy_db/src/views/site_view.rs +++ b/lemmy_db/src/views/site_view.rs @@ -1,5 +1,5 @@ use crate::{ - schema::{site as site_table, user_}, + schema::{site, user_}, site::Site, user::{UserSafe, User_}, }; @@ -14,13 +14,13 @@ pub struct SiteView { impl SiteView { pub fn read(conn: &PgConnection) -> Result { - let site_join = site_table::table + let (site, creator) = site::table .inner_join(user_::table) .first::<(Site, User_)>(conn)?; Ok(SiteView { - site: site_join.0, - creator: site_join.1.to_safe(), + site, + creator: creator.to_safe(), }) } } diff --git a/lemmy_db/src/views/user_view.rs b/lemmy_db/src/views/user_view.rs index eb18afbc1..33c441be6 100644 --- a/lemmy_db/src/views/user_view.rs +++ b/lemmy_db/src/views/user_view.rs @@ -1,5 +1,6 @@ use crate::{ - schema::user_, + aggregates::user_aggregates::UserAggregates, + schema::{user_, user_aggregates}, user::{UserSafe, User_}, }; use diesel::{result::Error, *}; @@ -8,58 +9,63 @@ use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct UserViewSafe { pub user: UserSafe, - // TODO - // pub number_of_posts: i64, - // pub post_score: i64, - // pub number_of_comments: i64, - // pub comment_score: i64, + pub counts: UserAggregates, } +#[derive(Debug, Serialize, Clone)] pub struct UserViewDangerous { pub user: User_, - // TODO - // pub number_of_posts: i64, - // pub post_score: i64, - // pub number_of_comments: i64, - // pub comment_score: i64, + pub counts: UserAggregates, } impl UserViewDangerous { pub fn read(conn: &PgConnection, id: i32) -> Result { - let user = user_::table.find(id).first::(conn)?; - Ok(Self { user }) + let (user, counts) = user_::table + .find(id) + .inner_join(user_aggregates::table) + .first::<(User_, UserAggregates)>(conn)?; + Ok(Self { user, counts }) } } impl UserViewSafe { pub fn read(conn: &PgConnection, id: i32) -> Result { - let user = user_::table.find(id).first::(conn)?.to_safe(); - Ok(Self { user }) + let (user, counts) = user_::table + .find(id) + .inner_join(user_aggregates::table) + .first::<(User_, UserAggregates)>(conn)?; + Ok(Self { + user: user.to_safe(), + counts, + }) } pub fn admins(conn: &PgConnection) -> Result, Error> { let admins = user_::table - // TODO do joins here + .inner_join(user_aggregates::table) .filter(user_::admin.eq(true)) .order_by(user_::published) - .load::(conn)?; + .load::<(User_, UserAggregates)>(conn)?; Ok(vec_to_user_view_safe(admins)) } pub fn banned(conn: &PgConnection) -> Result, Error> { let banned = user_::table - // TODO do joins here + .inner_join(user_aggregates::table) .filter(user_::banned.eq(true)) - .load::(conn)?; + .load::<(User_, UserAggregates)>(conn)?; Ok(vec_to_user_view_safe(banned)) } } -fn vec_to_user_view_safe(users: Vec) -> Vec { +fn vec_to_user_view_safe(users: Vec<(User_, UserAggregates)>) -> Vec { users .iter() - .map(|a| UserViewSafe { user: a.to_safe() }) + .map(|a| UserViewSafe { + user: a.0.to_safe(), + counts: a.1.to_owned(), + }) .collect::>() } diff --git a/lemmy_structs/src/site.rs b/lemmy_structs/src/site.rs index 12fda258b..dbbb37c4c 100644 --- a/lemmy_structs/src/site.rs +++ b/lemmy_structs/src/site.rs @@ -1,10 +1,10 @@ use lemmy_db::{ + aggregates::site_aggregates::SiteAggregates, category::*, comment_view::*, community_view::*, moderator_views::*, post_view::*, - site_aggregates::SiteAggregates, user::*, user_view::*, views::site_view::SiteView, diff --git a/migrations/2020-12-03-035643_create_user_aggregates/up.sql b/migrations/2020-12-03-035643_create_user_aggregates/up.sql index 85a0b675b..8d46fbfbe 100644 --- a/migrations/2020-12-03-035643_create_user_aggregates/up.sql +++ b/migrations/2020-12-03-035643_create_user_aggregates/up.sql @@ -60,11 +60,17 @@ returns trigger language plpgsql as $$ begin IF (TG_OP = 'INSERT') THEN + -- TODO not sure if this is working right + -- Need to get the post creator, not the voter update user_aggregates - set post_score = post_score + NEW.score where user_id = NEW.user_id; + set post_score = post_score + NEW.score + from post_like pl join post p on p.id = pl.post_id + where p.id = NEW.post_id and p.creator_id = NEW.user_id; ELSIF (TG_OP = 'DELETE') THEN update user_aggregates - set post_score = post_score - OLD.score where user_id = OLD.user_id; + set post_score = post_score - OLD.score + from post_like pl join post p on p.id = pl.post_id + where p.id = OLD.post_id and p.creator_id = OLD.user_id; END IF; return null; end $$; @@ -98,11 +104,16 @@ returns trigger language plpgsql as $$ begin IF (TG_OP = 'INSERT') THEN + -- Need to get the post creator, not the voter update user_aggregates - set comment_score = comment_score + NEW.score where user_id = NEW.user_id; + set comment_score = comment_score + NEW.score + from comment_like pl join comment p on p.id = pl.comment_id + where p.id = NEW.comment_id and p.creator_id = NEW.user_id; ELSIF (TG_OP = 'DELETE') THEN update user_aggregates - set comment_score = comment_score - OLD.score where user_id = OLD.user_id; + set comment_score = comment_score - OLD.score + from comment_like pl join comment p on p.id = pl.comment_id + where p.id = OLD.comment_id and p.creator_id = OLD.user_id; END IF; return null; end $$;