Starting to work on community view, 2
This commit is contained in:
parent
88d7b0a83c
commit
efdcbc44c4
7 changed files with 143 additions and 16 deletions
|
@ -36,6 +36,7 @@
|
|||
- [Rust docker build](https://shaneutt.com/blog/rust-fast-small-docker-image-builds/)
|
||||
- [Zurb mentions](https://github.com/zurb/tribute)
|
||||
- [TippyJS](https://github.com/atomiks/tippyjs)
|
||||
- [SQL function indexes](https://sorentwo.com/2013/12/30/let-postgres-do-the-work.html)
|
||||
|
||||
## Activitypub guides
|
||||
|
||||
|
|
21
lemmy_db/src/aggregates/community_aggregates.rs
Normal file
21
lemmy_db/src/aggregates/community_aggregates.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
use crate::schema::community_aggregates;
|
||||
use diesel::{result::Error, *};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
||||
#[table_name = "community_aggregates"]
|
||||
pub struct CommunityAggregates {
|
||||
pub id: i32,
|
||||
pub community_id: i32,
|
||||
pub subscribers: i64,
|
||||
pub posts: i64,
|
||||
pub counts: i64,
|
||||
}
|
||||
|
||||
impl CommunityAggregates {
|
||||
pub fn read(conn: &PgConnection, id: i32) -> Result<Self, Error> {
|
||||
community_aggregates::table.find(id).first::<Self>(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add unit tests, to make sure triggers are working
|
|
@ -1,2 +1,3 @@
|
|||
pub mod community_aggregates;
|
||||
pub mod site_aggregates;
|
||||
pub mod user_aggregates;
|
||||
|
|
|
@ -127,6 +127,16 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
community_aggregates (id) {
|
||||
id -> Int4,
|
||||
community_id -> Int4,
|
||||
subscribers -> Int8,
|
||||
posts -> Int8,
|
||||
comments -> Int8,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
community_aggregates_fast (id) {
|
||||
id -> Int4,
|
||||
|
@ -544,6 +554,7 @@ joinable!(comment_saved -> comment (comment_id));
|
|||
joinable!(comment_saved -> user_ (user_id));
|
||||
joinable!(community -> category (category_id));
|
||||
joinable!(community -> user_ (creator_id));
|
||||
joinable!(community_aggregates -> community (community_id));
|
||||
joinable!(community_follower -> community (community_id));
|
||||
joinable!(community_follower -> user_ (user_id));
|
||||
joinable!(community_moderator -> community (community_id));
|
||||
|
@ -587,6 +598,7 @@ allow_tables_to_appear_in_same_query!(
|
|||
comment_report,
|
||||
comment_saved,
|
||||
community,
|
||||
community_aggregates,
|
||||
community_aggregates_fast,
|
||||
community_follower,
|
||||
community_moderator,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
aggregates::community_aggregates::CommunityAggregates,
|
||||
category::Category,
|
||||
community::{Community, CommunityFollower},
|
||||
schema::{category, community, community_follower, user_},
|
||||
schema::{category, community, community_aggregates, community_follower, user_},
|
||||
user::{UserSafe, User_},
|
||||
};
|
||||
use diesel::{result::Error, *};
|
||||
|
@ -13,21 +14,9 @@ pub struct CommunityView {
|
|||
pub creator: UserSafe,
|
||||
pub category: Category,
|
||||
pub subscribed: bool,
|
||||
pub counts: CommunityAggregates,
|
||||
}
|
||||
|
||||
// creator_actor_id -> Text,
|
||||
// creator_local -> Bool,
|
||||
// creator_name -> Varchar,
|
||||
// creator_preferred_username -> Nullable<Varchar>,
|
||||
// creator_avatar -> Nullable<Text>,
|
||||
// category_name -> Varchar,
|
||||
// number_of_subscribers -> BigInt,
|
||||
// number_of_posts -> BigInt,
|
||||
// number_of_comments -> BigInt,
|
||||
// hot_rank -> Int4,
|
||||
// user_id -> Nullable<Int4>,
|
||||
// subscribed -> Nullable<Bool>,
|
||||
|
||||
impl CommunityView {
|
||||
pub fn read(
|
||||
conn: &PgConnection,
|
||||
|
@ -45,17 +34,19 @@ impl CommunityView {
|
|||
None => false,
|
||||
};
|
||||
|
||||
let (community, creator, category) = community::table
|
||||
let (community, creator, category, counts) = community::table
|
||||
.find(community_id)
|
||||
.inner_join(user_::table)
|
||||
.inner_join(category::table)
|
||||
.first::<(Community, User_, Category)>(conn)?;
|
||||
.inner_join(community_aggregates::table)
|
||||
.first::<(Community, User_, Category, CommunityAggregates)>(conn)?;
|
||||
|
||||
Ok(CommunityView {
|
||||
community,
|
||||
creator: creator.to_safe(),
|
||||
category,
|
||||
subscribed,
|
||||
counts,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
-- community aggregates
|
||||
drop table community_aggregates;
|
||||
drop trigger community_aggregates_post_count on post;
|
||||
drop trigger community_aggregates_comment_count on comment;
|
||||
drop trigger community_aggregates_subscriber_count on community_follower;
|
||||
drop function
|
||||
community_aggregates_post_count,
|
||||
community_aggregates_comment_count,
|
||||
community_aggregates_subscriber_count;
|
|
@ -0,0 +1,92 @@
|
|||
-- Add community aggregates
|
||||
create table community_aggregates (
|
||||
id serial primary key,
|
||||
community_id int references community on update cascade on delete cascade not null,
|
||||
subscribers bigint not null,
|
||||
posts bigint not null,
|
||||
comments bigint not null,
|
||||
unique (community_id)
|
||||
);
|
||||
|
||||
insert into community_aggregates (community_id, subscribers, posts, comments)
|
||||
select
|
||||
c.id,
|
||||
coalesce(cf.subs, 0::bigint) as subscribers,
|
||||
coalesce(cd.posts, 0::bigint) as posts,
|
||||
coalesce(cd.comments, 0::bigint) as comments
|
||||
from community c
|
||||
left join (
|
||||
select
|
||||
p.community_id,
|
||||
count(distinct p.id) as posts,
|
||||
count(distinct ct.id) as comments
|
||||
from post p
|
||||
left join comment ct on p.id = ct.post_id
|
||||
group by p.community_id
|
||||
) cd on cd.community_id = c.id
|
||||
left join (
|
||||
select
|
||||
community_follower.community_id,
|
||||
count(*) as subs
|
||||
from community_follower
|
||||
group by community_follower.community_id
|
||||
) cf on cf.community_id = c.id;
|
||||
|
||||
-- Add community aggregate triggers
|
||||
-- post count
|
||||
create function community_aggregates_post_count()
|
||||
returns trigger language plpgsql
|
||||
as $$
|
||||
begin
|
||||
IF (TG_OP = 'INSERT') THEN
|
||||
update community_aggregates
|
||||
set posts = posts + 1 where community_id = NEW.community_id;
|
||||
ELSIF (TG_OP = 'DELETE') THEN
|
||||
update community_aggregates
|
||||
set posts = posts - 1 where community_id = OLD.community_id;
|
||||
END IF;
|
||||
return null;
|
||||
end $$;
|
||||
|
||||
create trigger community_aggregates_post_count
|
||||
after insert or delete on post
|
||||
execute procedure community_aggregates_post_count();
|
||||
|
||||
-- comment count
|
||||
create function community_aggregates_comment_count()
|
||||
returns trigger language plpgsql
|
||||
as $$
|
||||
begin
|
||||
IF (TG_OP = 'INSERT') THEN
|
||||
update community_aggregates
|
||||
set comments = comments + 1 where community_id = NEW.community_id;
|
||||
ELSIF (TG_OP = 'DELETE') THEN
|
||||
update community_aggregates
|
||||
set comments = comments - 1 where community_id = OLD.community_id;
|
||||
END IF;
|
||||
return null;
|
||||
end $$;
|
||||
|
||||
create trigger community_aggregates_comment_count
|
||||
after insert or delete on comment
|
||||
execute procedure community_aggregates_comment_count();
|
||||
|
||||
-- subscriber count
|
||||
create function community_aggregates_subscriber_count()
|
||||
returns trigger language plpgsql
|
||||
as $$
|
||||
begin
|
||||
IF (TG_OP = 'INSERT') THEN
|
||||
update community_aggregates
|
||||
set subscribers = subscribers + 1 where community_id = NEW.community_id;
|
||||
ELSIF (TG_OP = 'DELETE') THEN
|
||||
update community_aggregates
|
||||
set subscribers = subscribers - 1 where community_id = OLD.community_id;
|
||||
END IF;
|
||||
return null;
|
||||
end $$;
|
||||
|
||||
create trigger community_aggregates_subscriber_count
|
||||
after insert or delete on community_follower
|
||||
execute procedure community_aggregates_subscriber_count();
|
||||
|
Loading…
Reference in a new issue