Switch to sqlite (#22)

* Updated project to use sqlite

* Edited migrations directly because I fear no man

* Updated search functions and tests to work with sqlite

* Updated build tools to remove postgres
This commit is contained in:
Kieran
2024-02-16 10:11:41 -08:00
committed by GitHub
parent 44bd105e80
commit 8fcd41f45d
29 changed files with 121 additions and 186 deletions
+21 -20
View File
@@ -51,31 +51,29 @@ defmodule Pinchflat.Media do
Returns a list of media_items that match the search term. Adds a `matching_search_term`
virtual field to the result set.
Has explit handling for blank search terms because SQLite doesn't like empty MATCH clauses.
Returns [%MediaItem{}, ...].
"""
def search(search_term, opts \\ []) do
def search(_search_term, _opts \\ [])
def search("", _opts), do: []
def search(nil, _opts), do: []
def search(search_term, opts) do
limit = Keyword.get(opts, :limit, 50)
from(mi in MediaItem,
where: fragment("searchable @@ websearch_to_tsquery(?)", ^search_term),
join: mi_search_index in assoc(mi, :media_items_search_index),
where: fragment("media_items_search_index MATCH ?", ^search_term),
select_merge: %{
matching_search_term:
fragment(
"""
ts_headline(
'english',
CONCAT(title, ' ', description),
websearch_to_tsquery(?),
'StartSel=[PF_HIGHLIGHT],StopSel=[/PF_HIGHLIGHT]'
)
""",
^search_term
)
},
order_by: {
:desc,
fragment("ts_rank_cd(searchable, websearch_to_tsquery(?), 0)", ^search_term)
fragment("""
snippet(media_items_search_index, 0, '[PF_HIGHLIGHT]', '[/PF_HIGHLIGHT]', '...', 20) ||
' ' ||
snippet(media_items_search_index, 1, '[PF_HIGHLIGHT]', '[/PF_HIGHLIGHT]', '...', 20)
""")
},
order_by: [desc: fragment("rank")],
limit: ^limit
)
|> Repo.all()
@@ -174,7 +172,10 @@ defmodule Pinchflat.Media do
Enum.reduce(mapped_struct, dynamic(true), fn attr, dynamic ->
case {attr, media_profile} do
{{:shorts_behaviour, :only}, %{livestream_behaviour: :only}} ->
dynamic([mi], ^dynamic and (mi.livestream == true or fragment("? ILIKE ?", mi.original_url, "%/shorts/%")))
dynamic(
[mi],
^dynamic and (mi.livestream == true or fragment("LOWER(?) LIKE LOWER(?)", mi.original_url, "%/shorts/%"))
)
# Technically redundant, but makes the other clauses easier to parse
# (redundant because this condition is the same as the condition above, just flipped)
@@ -183,7 +184,7 @@ defmodule Pinchflat.Media do
{{:shorts_behaviour, :only}, _} ->
# return records with /shorts/ in the original_url
dynamic([mi], ^dynamic and fragment("? ILIKE ?", mi.original_url, "%/shorts/%"))
dynamic([mi], ^dynamic and fragment("LOWER(?) LIKE LOWER(?)", mi.original_url, "%/shorts/%"))
{{:livestream_behaviour, :only}, _} ->
# return records with livestream: true
@@ -191,7 +192,7 @@ defmodule Pinchflat.Media do
{{:shorts_behaviour, :exclude}, %{livestream_behaviour: lb}} when lb != :only ->
# return records without /shorts/ in the original_url
dynamic([mi], ^dynamic and fragment("? NOT ILIKE ?", mi.original_url, "%/shorts/%"))
dynamic([mi], ^dynamic and fragment("LOWER(?) NOT LIKE LOWER(?)", mi.original_url, "%/shorts/%"))
{{:livestream_behaviour, :exclude}, %{shorts_behaviour: sb}} when sb != :only ->
# return records with livestream: false
+2
View File
@@ -9,6 +9,7 @@ defmodule Pinchflat.Media.MediaItem do
alias Pinchflat.Tasks.Task
alias Pinchflat.MediaSource.Source
alias Pinchflat.Media.MediaMetadata
alias Pinchflat.Media.MediaItemSearchIndex
@allowed_fields ~w(
title
@@ -46,6 +47,7 @@ defmodule Pinchflat.Media.MediaItem do
belongs_to :source, Source
has_one :metadata, MediaMetadata, on_replace: :update
has_one :media_items_search_index, MediaItemSearchIndex, foreign_key: :id
has_many :tasks, Task
@@ -0,0 +1,16 @@
defmodule Pinchflat.Media.MediaItemSearchIndex do
@moduledoc """
The MediaItem fts5 search index. Not made to be directly interacted with,
but I figured it'd be better to have it in-app so it's not a mystery.
"""
use Ecto.Schema
@primary_key {:id, :id, autogenerate: true, source: :rowid}
schema "media_items_search_index" do
field :title, :string
field :description, :string
field :rank, :float, virtual: true
end
end
+1 -1
View File
@@ -1,7 +1,7 @@
defmodule Pinchflat.Repo do
use Ecto.Repo,
otp_app: :pinchflat,
adapter: Ecto.Adapters.Postgres
adapter: Ecto.Adapters.SQLite3
@doc """
It's not immediately obvious if an Oban job qualifies as unique, so this method