Skip to content

WIP: Add trending vote sort to topic voting plugin#38839

Draft
ZogStriP wants to merge 3 commits intomainfrom
topic-voting-trending-sort
Draft

WIP: Add trending vote sort to topic voting plugin#38839
ZogStriP wants to merge 3 commits intomainfrom
topic-voting-trending-sort

Conversation

@ZogStriP
Copy link
Member

The existing "Votes" sort orders topics by all-time vote count, which causes old, resolved topics to permanently dominate the list. Communities using the voting plugin have been asking for a way to surface topics gaining traction recently since 2016.

This adds a "Trending" sort that uses a time-decay formula where each vote contributes 1 / (age_in_hours + 2) to the topic's trending score. Recent votes naturally weigh more — a vote cast 1 hour ago scores ~0.33 while a vote cast 30 days ago scores ~0.001. No windows, thresholds, or scheduled jobs needed.

The sort is available via ?order=votes-trending on topic lists and through the new "Trending" navigation tab in voting-enabled categories. It also works with the TopicsFilter query string (order:votes-trending). All-time vote count is used as a tiebreaker, then bumped_at.

A composite index on (topic_id, created_at) is added to topic_voting_votes to keep the correlated subquery fast.

The JS initializer is also refactored to reduce duplication across the three voting navigation bar items.

Ref - t/180396

@github-actions github-actions bot added i18n PRs which update English locale files or i18n related code discourse-topic-voting labels Mar 24, 2026
@ZogStriP ZogStriP force-pushed the topic-voting-trending-sort branch from 98c8b9f to 8bc459b Compare March 24, 2026 23:10
The existing "Votes" sort orders topics by all-time vote count,
which causes old, resolved topics to permanently dominate the list.
Communities using the voting plugin have been asking for a way to
surface topics gaining traction *recently* since 2016.

This adds a "Trending" sort that uses a time-decay formula where
each vote contributes `1 / (age_in_hours + 2)` to the topic's
trending score. Recent votes naturally weigh more — a vote cast
1 hour ago scores ~0.33 while a vote cast 30 days ago scores
~0.001. No windows, thresholds, or scheduled jobs needed.

The sort is available via `?order=votes-trending` on topic lists
and through the new "Trending" navigation tab in voting-enabled
categories. It also works with the TopicsFilter query string
(`order:votes-trending`). All-time vote count is used as a
tiebreaker, then bumped_at.

A composite index on `(topic_id, created_at)` is added to
`topic_voting_votes` to keep the correlated subquery fast.

The JS initializer is also refactored to reduce duplication
across the three voting navigation bar items.

Ref - t/180396
Discourse enforces a safety check that prevents creating indexes
concurrently without first dropping any existing (potentially invalid)
index. This follows the Postgres recommendation that if a concurrent
index build fails, it leaves behind an invalid index that should be
dropped before retrying.

Replace the single `add_index` with `if_not_exists` by an explicit
`remove_index` with `if_exists` followed by `add_index` with
`algorithm: :concurrently`, which satisfies the safety check.
@ZogStriP ZogStriP force-pushed the topic-voting-trending-sort branch from 8bc459b to 0206c28 Compare March 24, 2026 23:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

discourse-topic-voting i18n PRs which update English locale files or i18n related code

Development

Successfully merging this pull request may close these issues.

1 participant