Adding a new comment sort for posts. Fixes #1294 (#1425)

* Adding a new comment sort. Fixes #1294

* Fixing a migration comment.

* Adding a comment for newest_comment_time_necro
This commit is contained in:
Dessalines 2021-02-18 10:38:25 -05:00 committed by GitHub
parent 6f683682c3
commit 0c4b57a6d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 98 additions and 7 deletions

View file

@ -1 +1 @@
*.sql *.sqldump

View file

@ -1,5 +1,5 @@
tab_spaces = 2 tab_spaces = 2
edition="2018" edition="2018"
imports_layout="HorizontalVertical" imports_layout="HorizontalVertical"
merge_imports=true imports_granularity="Crate"
reorder_imports=true reorder_imports=true

View file

@ -13,6 +13,7 @@ pub struct PostAggregates {
pub downvotes: i64, pub downvotes: i64,
pub stickied: bool, pub stickied: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
pub newest_comment_time_necro: chrono::NaiveDateTime, // A newest comment time, limited to 2 days, to prevent necrobumping
pub newest_comment_time: chrono::NaiveDateTime, pub newest_comment_time: chrono::NaiveDateTime,
} }

View file

@ -165,6 +165,7 @@ pub enum SortType {
TopYear, TopYear,
TopAll, TopAll,
MostComments, MostComments,
NewComments,
} }
#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone)] #[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone)]

View file

@ -291,6 +291,7 @@ table! {
downvotes -> Int8, downvotes -> Int8,
stickied -> Bool, stickied -> Bool,
published -> Timestamp, published -> Timestamp,
newest_comment_time_necro -> Timestamp,
newest_comment_time -> Timestamp, newest_comment_time -> Timestamp,
} }
} }

View file

@ -380,7 +380,9 @@ impl<'a> CommentQueryBuilder<'a> {
SortType::Hot | SortType::Active => query SortType::Hot | SortType::Active => query
.order_by(hot_rank(comment_aggregates::score, comment_aggregates::published).desc()) .order_by(hot_rank(comment_aggregates::score, comment_aggregates::published).desc())
.then_order_by(comment_aggregates::published.desc()), .then_order_by(comment_aggregates::published.desc()),
SortType::New | SortType::MostComments => query.order_by(comment::published.desc()), SortType::New | SortType::MostComments | SortType::NewComments => {
query.order_by(comment::published.desc())
}
SortType::TopAll => query.order_by(comment_aggregates::score.desc()), SortType::TopAll => query.order_by(comment_aggregates::score.desc()),
SortType::TopYear => query SortType::TopYear => query
.filter(comment::published.gt(now - 1.years())) .filter(comment::published.gt(now - 1.years()))

View file

@ -356,14 +356,19 @@ impl<'a> PostQueryBuilder<'a> {
query = match self.sort { query = match self.sort {
SortType::Active => query SortType::Active => query
.then_order_by( .then_order_by(
hot_rank(post_aggregates::score, post_aggregates::newest_comment_time).desc(), hot_rank(
post_aggregates::score,
post_aggregates::newest_comment_time_necro,
)
.desc(),
) )
.then_order_by(post_aggregates::newest_comment_time.desc()), .then_order_by(post_aggregates::newest_comment_time_necro.desc()),
SortType::Hot => query SortType::Hot => query
.then_order_by(hot_rank(post_aggregates::score, post_aggregates::published).desc()) .then_order_by(hot_rank(post_aggregates::score, post_aggregates::published).desc())
.then_order_by(post_aggregates::published.desc()), .then_order_by(post_aggregates::published.desc()),
SortType::New => query.then_order_by(post_aggregates::published.desc()), SortType::New => query.then_order_by(post_aggregates::published.desc()),
SortType::MostComments => query.then_order_by(post_aggregates::comments.desc()), SortType::MostComments => query.then_order_by(post_aggregates::comments.desc()),
SortType::NewComments => query.then_order_by(post_aggregates::newest_comment_time.desc()),
SortType::TopAll => query.then_order_by(post_aggregates::score.desc()), SortType::TopAll => query.then_order_by(post_aggregates::score.desc()),
SortType::TopYear => query SortType::TopYear => query
.filter(post::published.gt(now - 1.years())) .filter(post::published.gt(now - 1.years()))
@ -623,6 +628,7 @@ mod tests {
downvotes: 0, downvotes: 0,
stickied: false, stickied: false,
published: agg.published, published: agg.published,
newest_comment_time_necro: inserted_post.published,
newest_comment_time: inserted_post.published, newest_comment_time: inserted_post.published,
}, },
subscribed: false, subscribed: false,

View file

@ -270,7 +270,9 @@ impl<'a> UserMentionQueryBuilder<'a> {
SortType::Hot | SortType::Active => query SortType::Hot | SortType::Active => query
.order_by(hot_rank(comment_aggregates::score, comment_aggregates::published).desc()) .order_by(hot_rank(comment_aggregates::score, comment_aggregates::published).desc())
.then_order_by(comment_aggregates::published.desc()), .then_order_by(comment_aggregates::published.desc()),
SortType::New | SortType::MostComments => query.order_by(comment::published.desc()), SortType::New | SortType::MostComments | SortType::NewComments => {
query.order_by(comment::published.desc())
}
SortType::TopAll => query.order_by(comment_aggregates::score.desc()), SortType::TopAll => query.order_by(comment_aggregates::score.desc()),
SortType::TopYear => query SortType::TopYear => query
.filter(comment::published.gt(now - 1.years())) .filter(comment::published.gt(now - 1.years()))

View file

@ -110,7 +110,9 @@ impl<'a> UserQueryBuilder<'a> {
SortType::Active => query SortType::Active => query
.order_by(user_aggregates::comment_score.desc()) .order_by(user_aggregates::comment_score.desc())
.then_order_by(user_::published.desc()), .then_order_by(user_::published.desc()),
SortType::New | SortType::MostComments => query.order_by(user_::published.desc()), SortType::New | SortType::MostComments | SortType::NewComments => {
query.order_by(user_::published.desc())
}
SortType::TopAll => query.order_by(user_aggregates::comment_score.desc()), SortType::TopAll => query.order_by(user_aggregates::comment_score.desc()),
SortType::TopYear => query SortType::TopYear => query
.filter(user_::published.gt(now - 1.years())) .filter(user_::published.gt(now - 1.years()))

View file

@ -0,0 +1,33 @@
drop index idx_post_aggregates_newest_comment_time,
idx_post_aggregates_stickied_newest_comment_time,
idx_post_aggregates_stickied_comments;
alter table post_aggregates drop column newest_comment_time;
alter table post_aggregates rename column newest_comment_time_necro to newest_comment_time;
create or replace function post_aggregates_comment_count()
returns trigger language plpgsql
as $$
begin
IF (TG_OP = 'INSERT') THEN
update post_aggregates pa
set comments = comments + 1
where pa.post_id = NEW.post_id;
-- A 2 day necro-bump limit
update post_aggregates pa
set newest_comment_time = NEW.published
where pa.post_id = NEW.post_id
and published > ('now'::timestamp - '2 days'::interval);
ELSIF (TG_OP = 'DELETE') THEN
-- Join to post because that post may not exist anymore
update post_aggregates pa
set comments = comments - 1
from post p
where pa.post_id = p.id
and pa.post_id = OLD.post_id;
END IF;
return null;
end $$;

View file

@ -0,0 +1,43 @@
-- First rename current newest comment time to newest_comment_time_necro
-- necro means that time is limited to 2 days, whereas newest_comment_time ignores that.
alter table post_aggregates rename column newest_comment_time to newest_comment_time_necro;
-- Add the newest_comment_time column
alter table post_aggregates add column newest_comment_time timestamp not null default now();
-- Set the current newest_comment_time based on the old ones
update post_aggregates set newest_comment_time = newest_comment_time_necro;
-- Add the indexes for this new column
create index idx_post_aggregates_newest_comment_time on post_aggregates (newest_comment_time desc);
create index idx_post_aggregates_stickied_newest_comment_time on post_aggregates (stickied desc, newest_comment_time desc);
-- Forgot to add index w/ stickied first for most comments:
create index idx_post_aggregates_stickied_comments on post_aggregates (stickied desc, comments desc);
-- Alter the comment trigger to set the newest_comment_time, and newest_comment_time_necro
create or replace function post_aggregates_comment_count()
returns trigger language plpgsql
as $$
begin
IF (TG_OP = 'INSERT') THEN
update post_aggregates pa
set comments = comments + 1,
newest_comment_time = NEW.published
where pa.post_id = NEW.post_id;
-- A 2 day necro-bump limit
update post_aggregates pa
set newest_comment_time_necro = NEW.published
where pa.post_id = NEW.post_id
and published > ('now'::timestamp - '2 days'::interval);
ELSIF (TG_OP = 'DELETE') THEN
-- Join to post because that post may not exist anymore
update post_aggregates pa
set comments = comments - 1
from post p
where pa.post_id = p.id
and pa.post_id = OLD.post_id;
END IF;
return null;
end $$;