More user aggregates.

This commit is contained in:
Dessalines 2020-12-03 13:39:56 -05:00
parent d66f4e8ac0
commit 6d8f93d8a1
9 changed files with 73 additions and 32 deletions

View file

@ -10,6 +10,7 @@ use actix_web::web::Data;
use anyhow::Context; use anyhow::Context;
use lemmy_apub::fetcher::search_by_apub_id; use lemmy_apub::fetcher::search_by_apub_id;
use lemmy_db::{ use lemmy_db::{
aggregates::site_aggregates::SiteAggregates,
category::*, category::*,
comment_view::*, comment_view::*,
community_view::*, community_view::*,
@ -19,7 +20,6 @@ use lemmy_db::{
naive_now, naive_now,
post_view::*, post_view::*,
site::*, site::*,
site_aggregates::SiteAggregates,
user_view::*, user_view::*,
views::site_view::SiteView, views::site_view::SiteView,
Crud, Crud,

View file

@ -0,0 +1,2 @@
pub mod site_aggregates;
pub mod user_aggregates;

View file

@ -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<Self, Error> {
user_aggregates::table.find(id).first::<Self>(conn)
}
}
// TODO add unit tests, to make sure triggers are working

View file

@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize};
use std::{env, env::VarError}; use std::{env, env::VarError};
pub mod activity; pub mod activity;
pub mod aggregates;
pub mod category; pub mod category;
pub mod comment; pub mod comment;
pub mod comment_report; pub mod comment_report;
@ -28,7 +29,6 @@ pub mod private_message;
pub mod private_message_view; pub mod private_message_view;
pub mod schema; pub mod schema;
pub mod site; pub mod site;
pub mod site_aggregates;
pub mod user; pub mod user;
pub mod user_mention; pub mod user_mention;
pub mod user_mention_view; pub mod user_mention_view;

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
schema::{site as site_table, user_}, schema::{site, user_},
site::Site, site::Site,
user::{UserSafe, User_}, user::{UserSafe, User_},
}; };
@ -14,13 +14,13 @@ pub struct SiteView {
impl SiteView { impl SiteView {
pub fn read(conn: &PgConnection) -> Result<Self, Error> { pub fn read(conn: &PgConnection) -> Result<Self, Error> {
let site_join = site_table::table let (site, creator) = site::table
.inner_join(user_::table) .inner_join(user_::table)
.first::<(Site, User_)>(conn)?; .first::<(Site, User_)>(conn)?;
Ok(SiteView { Ok(SiteView {
site: site_join.0, site,
creator: site_join.1.to_safe(), creator: creator.to_safe(),
}) })
} }
} }

View file

@ -1,5 +1,6 @@
use crate::{ use crate::{
schema::user_, aggregates::user_aggregates::UserAggregates,
schema::{user_, user_aggregates},
user::{UserSafe, User_}, user::{UserSafe, User_},
}; };
use diesel::{result::Error, *}; use diesel::{result::Error, *};
@ -8,58 +9,63 @@ use serde::Serialize;
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct UserViewSafe { pub struct UserViewSafe {
pub user: UserSafe, pub user: UserSafe,
// TODO pub counts: UserAggregates,
// pub number_of_posts: i64,
// pub post_score: i64,
// pub number_of_comments: i64,
// pub comment_score: i64,
} }
#[derive(Debug, Serialize, Clone)]
pub struct UserViewDangerous { pub struct UserViewDangerous {
pub user: User_, pub user: User_,
// TODO pub counts: UserAggregates,
// pub number_of_posts: i64,
// pub post_score: i64,
// pub number_of_comments: i64,
// pub comment_score: i64,
} }
impl UserViewDangerous { impl UserViewDangerous {
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> { pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
let user = user_::table.find(id).first::<User_>(conn)?; let (user, counts) = user_::table
Ok(Self { user }) .find(id)
.inner_join(user_aggregates::table)
.first::<(User_, UserAggregates)>(conn)?;
Ok(Self { user, counts })
} }
} }
impl UserViewSafe { impl UserViewSafe {
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> { pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
let user = user_::table.find(id).first::<User_>(conn)?.to_safe(); let (user, counts) = user_::table
Ok(Self { user }) .find(id)
.inner_join(user_aggregates::table)
.first::<(User_, UserAggregates)>(conn)?;
Ok(Self {
user: user.to_safe(),
counts,
})
} }
pub fn admins(conn: &PgConnection) -> Result<Vec<Self>, Error> { pub fn admins(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let admins = user_::table let admins = user_::table
// TODO do joins here .inner_join(user_aggregates::table)
.filter(user_::admin.eq(true)) .filter(user_::admin.eq(true))
.order_by(user_::published) .order_by(user_::published)
.load::<User_>(conn)?; .load::<(User_, UserAggregates)>(conn)?;
Ok(vec_to_user_view_safe(admins)) Ok(vec_to_user_view_safe(admins))
} }
pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> { pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> {
let banned = user_::table let banned = user_::table
// TODO do joins here .inner_join(user_aggregates::table)
.filter(user_::banned.eq(true)) .filter(user_::banned.eq(true))
.load::<User_>(conn)?; .load::<(User_, UserAggregates)>(conn)?;
Ok(vec_to_user_view_safe(banned)) Ok(vec_to_user_view_safe(banned))
} }
} }
fn vec_to_user_view_safe(users: Vec<User_>) -> Vec<UserViewSafe> { fn vec_to_user_view_safe(users: Vec<(User_, UserAggregates)>) -> Vec<UserViewSafe> {
users users
.iter() .iter()
.map(|a| UserViewSafe { user: a.to_safe() }) .map(|a| UserViewSafe {
user: a.0.to_safe(),
counts: a.1.to_owned(),
})
.collect::<Vec<UserViewSafe>>() .collect::<Vec<UserViewSafe>>()
} }

View file

@ -1,10 +1,10 @@
use lemmy_db::{ use lemmy_db::{
aggregates::site_aggregates::SiteAggregates,
category::*, category::*,
comment_view::*, comment_view::*,
community_view::*, community_view::*,
moderator_views::*, moderator_views::*,
post_view::*, post_view::*,
site_aggregates::SiteAggregates,
user::*, user::*,
user_view::*, user_view::*,
views::site_view::SiteView, views::site_view::SiteView,

View file

@ -60,11 +60,17 @@ returns trigger language plpgsql
as $$ as $$
begin begin
IF (TG_OP = 'INSERT') THEN 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 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 ELSIF (TG_OP = 'DELETE') THEN
update user_aggregates 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; END IF;
return null; return null;
end $$; end $$;
@ -98,11 +104,16 @@ returns trigger language plpgsql
as $$ as $$
begin begin
IF (TG_OP = 'INSERT') THEN IF (TG_OP = 'INSERT') THEN
-- Need to get the post creator, not the voter
update user_aggregates 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 ELSIF (TG_OP = 'DELETE') THEN
update user_aggregates 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; END IF;
return null; return null;
end $$; end $$;