From 3ad16118f906bd0ce5ba34716ff41685c485827b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Larre=20Borges?= Date: Wed, 9 Oct 2024 17:54:03 +0200 Subject: [PATCH] Limit user entries in the Recent to 2 per day This is an attempt to reduce self-promotion and keep the number of bookmarks in the Recent view to a relatively small number. --- lib/linkhut/links.ex | 9 ++-- lib/linkhut/links/public_link.ex | 8 ++-- lib/linkhut/links/tags.ex | 3 +- lib/linkhut/tags.ex | 2 - ...110848_add_inserted_at_to_public_links.exs | 48 +++++++++++++++++++ 5 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 priv/repo/migrations/20241008110848_add_inserted_at_to_public_links.exs diff --git a/lib/linkhut/links.ex b/lib/linkhut/links.ex index 3a01593..64e7fda 100644 --- a/lib/linkhut/links.ex +++ b/lib/linkhut/links.ex @@ -228,9 +228,10 @@ defmodule Linkhut.Links do datetime = DateTime.add(DateTime.now!("Etc/UTC"), -days, :day) links() - |> where([l, s, _], l.inserted_at == s.last) |> where(is_private: false) |> where(is_unread: false) + |> where([_, s], s.user_daily_entry <= 2) + |> where([_, s], s.rank == 0.0) |> where([l], l.inserted_at >= ^datetime) |> ordering(params) end @@ -240,7 +241,7 @@ defmodule Linkhut.Links do """ def popular(params, popularity \\ 3) do links() - |> where([l, s, _], l.inserted_at == s.first) + |> where([l, s, _], s.rank == 1.0) |> where(is_private: false) |> where(is_unread: false) |> where([_, s, _], s.saves >= ^popularity) @@ -270,8 +271,8 @@ defmodule Linkhut.Links do def links(params \\ []) do from(l in Link, - left_join: s in PublicLink, - on: [url: l.url, user_id: l.user_id], + join: s in PublicLink, + on: [id: l.id], select_merge: ^select_fields(params), preload: [:user, :variants, :savers] ) diff --git a/lib/linkhut/links/public_link.ex b/lib/linkhut/links/public_link.ex index 4bc3a4a..de84a91 100644 --- a/lib/linkhut/links/public_link.ex +++ b/lib/linkhut/links/public_link.ex @@ -8,11 +8,11 @@ defmodule Linkhut.Links.PublicLink do @primary_key false schema "public_links" do - field :url, :string, primary_key: true - field :user_id, :id, primary_key: true + field :id, :integer, primary_key: true + field :inserted_at, :utc_datetime belongs_to :user, User, define_field: false field :saves, :integer - field :first, :utc_datetime - field :last, :utc_datetime + field :rank, :float + field :user_daily_entry, :integer end end diff --git a/lib/linkhut/links/tags.ex b/lib/linkhut/links/tags.ex index bed5e6c..cd9bb28 100644 --- a/lib/linkhut/links/tags.ex +++ b/lib/linkhut/links/tags.ex @@ -53,6 +53,7 @@ defmodule Linkhut.Links.Tags do end defp valid?(tag) do - String.valid?(tag) && String.length(tag) <= 128 && not String.starts_with?(tag, "~") + String.valid?(tag) && String.length(tag) <= 128 && not String.starts_with?(tag, "~") && + not String.starts_with?(tag, "-") end end diff --git a/lib/linkhut/tags.ex b/lib/linkhut/tags.ex index 46fd82b..668560b 100644 --- a/lib/linkhut/tags.ex +++ b/lib/linkhut/tags.ex @@ -70,8 +70,6 @@ defmodule Linkhut.Tags do count: count("*") }, group_by: fragment("lower(?)", t.tag) - - # order_by: [desc: count("*"), asc: fragment("label")] end defp ordering(query, opts) do diff --git a/priv/repo/migrations/20241008110848_add_inserted_at_to_public_links.exs b/priv/repo/migrations/20241008110848_add_inserted_at_to_public_links.exs new file mode 100644 index 0000000..9e6d765 --- /dev/null +++ b/priv/repo/migrations/20241008110848_add_inserted_at_to_public_links.exs @@ -0,0 +1,48 @@ +defmodule Linkhut.Repo.Migrations.Eifjcbfrhgfnurctrtbiftnfliinivrdtvbrthfejdib do + use Ecto.Migration + + def up do + execute "DROP MATERIALIZED VIEW IF EXISTS public_links;" + + execute """ + CREATE MATERIALIZED VIEW public_links AS + SELECT + l.id, + l.url, + l.user_id, + l.inserted_at, + percent_rank() OVER "reverse_order" AS "rank", + rank() OVER "daily_entry" AS "user_daily_entry", + count(l.url) OVER "distinct_link" AS "saves", + u.username AS "username" + FROM links l + JOIN users u on l.user_id = u.id + WHERE (NOT l.is_private AND NOT l.is_unread AND NOT u.unlisted) + WINDOW + "distinct_link" AS (PARTITION BY l.url), + "reverse_order" AS (PARTITION BY l.url ORDER BY l.inserted_at DESC), + "daily_entry" AS (PARTITION BY date_trunc('day', l.inserted_at), l.user_id ORDER BY l.inserted_at ASC) + """ + end + + def down do + execute "DROP MATERIALIZED VIEW IF EXISTS public_links;" + + execute """ + CREATE MATERIALIZED VIEW public_links AS + SELECT + l.id, + l.url, + l.user_id, + min(l.inserted_at) OVER "distinct_link" AS "first", + max(l.inserted_at) OVER "distinct_link" AS "last", + count(l.url) OVER "distinct_link" AS "saves", + u.username AS "username" + FROM links l + JOIN users u on l.user_id = u.id + WHERE (NOT l.is_private AND NOT l.is_unread AND NOT u.unlisted) + WINDOW "distinct_link" AS (PARTITION BY l.url) + ; + """ + end +end -- 2.45.2