This repository has been archived on 2023-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
bdfr-browser/lib/bdfr_browser/post.ex
Daniel Kempkens 65f8468daa
All checks were successful
Build / build (push) Successful in 4m10s
fix: Improved importing of duplicate posts and comments
2023-10-20 18:23:07 +02:00

193 lines
5.5 KiB
Elixir

defmodule BdfrBrowser.Post do
use Ecto.Schema
import Ecto.Query, only: [dynamic: 1, dynamic: 2, from: 2, having: 3]
alias BdfrBrowser.{Comment, Subreddit}
@primary_key {:id, :string, autogenerate: false}
schema "posts" do
field :title, :string
field :selftext, :string
field :url, :string
field :permalink, :string
field :author, :string
field :upvote_ratio, :float
field :posted_at, :utc_datetime
field :filename, :string
belongs_to :subreddit, Subreddit
has_many :comments, Comment
end
def date_listing(subreddits) when is_list(subreddits) do
subreddit_ids = for s <- subreddits, do: s.id
from(p in __MODULE__,
select: fragment("to_char(?, 'YYYY-MM')", p.posted_at),
where: p.subreddit_id in ^subreddit_ids,
distinct: true,
order_by: [desc: fragment("to_char(?, 'YYYY-MM')", p.posted_at)]
)
end
def date_listing(subreddit) do
from(p in __MODULE__,
select: fragment("to_char(?, 'YYYY-MM')", p.posted_at),
where: p.subreddit_id == ^subreddit.id,
distinct: true,
order_by: [desc: fragment("to_char(?, 'YYYY-MM')", p.posted_at)]
)
end
def during_month(subreddit, month_str) do
{:ok, d} = Date.from_iso8601("#{month_str}-01")
during_range(subreddit, Date.beginning_of_month(d), Date.end_of_month(d))
end
def during_range(subreddits, start_date, end_date, sort_field \\ :posted_at)
def during_range(subreddits, start_date, end_date, sort_field) when is_list(subreddits) do
subreddit_ids = for s <- subreddits, do: s.id
from(p in __MODULE__,
left_join: c in assoc(p, :comments),
join: s in assoc(p, :subreddit),
select: %{
id: p.id,
title: p.title,
url: p.url,
author: p.author,
posted_at: p.posted_at,
num_comments: selected_as(count(c.id), :num_comments),
subreddit: s.name,
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
},
where:
p.subreddit_id in ^subreddit_ids and type(p.posted_at, :date) >= ^start_date and
type(p.posted_at, :date) <= ^end_date,
order_by: ^dynamic_sort(sort_field),
group_by: [p.id, s.name]
)
end
def during_range(subreddit, start_date, end_date, sort_field) do
from(p in __MODULE__,
left_join: c in assoc(p, :comments),
join: s in assoc(p, :subreddit),
select: %{
id: p.id,
title: p.title,
url: p.url,
author: p.author,
posted_at: p.posted_at,
num_comments: selected_as(count(c.id), :num_comments),
subreddit: s.name,
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
},
where:
p.subreddit_id == ^subreddit.id and type(p.posted_at, :date) >= ^start_date and
type(p.posted_at, :date) <= ^end_date,
order_by: ^dynamic_sort(sort_field),
group_by: [p.id, s.name]
)
end
def with_comments(query, more_than \\ 0) do
having(query, [p, c, s], count(c.id) > ^more_than)
end
def get_import(id) do
from(p in __MODULE__,
select: %{
id: p.id
},
where: p.id == ^id
)
end
def get_full(id) do
from(p in __MODULE__,
where: p.id == ^id,
preload: [
comments:
^from(c in Comment,
where: is_nil(c.parent_id),
order_by: [asc: c.posted_at],
preload: [children: ^from(c1 in Comment, order_by: [asc: c1.posted_at])]
)
]
)
end
def by_author(author) do
from(p in __MODULE__,
left_join: c in assoc(p, :comments),
join: s in assoc(p, :subreddit),
select: %{
id: p.id,
title: p.title,
url: p.url,
posted_at: p.posted_at,
num_comments: count(c.id),
subreddit: s.name,
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
},
where: p.author == ^author,
order_by: [desc: p.posted_at],
group_by: [p.id, s.name]
)
end
def search(str), do: search(str, nil)
def search(str, subreddits) when is_nil(subreddits) do
from(p in __MODULE__,
left_join: c in assoc(p, :comments),
join: s in assoc(p, :subreddit),
select: %{
id: p.id,
title: p.title,
url: p.url,
author: p.author,
posted_at: p.posted_at,
num_comments: count(c.id),
subreddit: s.name,
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
},
where:
fragment("? @@ websearch_to_tsquery('english', ?)", p.searchable_content, ^str) or
fragment("? @@ websearch_to_tsquery('german', ?)", p.searchable_content, ^str),
order_by: [desc: p.posted_at],
group_by: [p.id, s.name]
)
end
def search(str, subreddits) when is_list(subreddits) do
from(p in __MODULE__,
left_join: c in assoc(p, :comments),
join: s in assoc(p, :subreddit),
select: %{
id: p.id,
title: p.title,
url: p.url,
author: p.author,
posted_at: p.posted_at,
num_comments: count(c.id),
subreddit: s.name,
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
},
where:
s.name in ^subreddits and
(fragment("? @@ websearch_to_tsquery('english', ?)", p.searchable_content, ^str) or
fragment("? @@ websearch_to_tsquery('german', ?)", p.searchable_content, ^str)),
order_by: [desc: p.posted_at],
group_by: [p.id, s.name]
)
end
defp dynamic_sort(:posted_at), do: [{:desc, dynamic([p], p.posted_at)}]
defp dynamic_sort(:most_comments), do: dynamic(fragment("num_comments DESC"))
end