Enable tagged search

This commit is contained in:
Claudio Ortolina
2024-10-10 09:56:36 +01:00
parent e30ba5ef3f
commit 201c2edc01
3 changed files with 112 additions and 18 deletions
+40 -17
View File
@@ -2,7 +2,7 @@ defmodule MusicLibrary.Records do
import Ecto.Query, warn: false
alias MusicLibrary.Repo
alias MusicLibrary.Records.Record
alias MusicLibrary.Records.{Record, SearchParser}
@fields [:id, :type, :artists, :format, :title, :release, :genres, :musicbrainz_id, :cover_hash]
@@ -24,15 +24,46 @@ defmodule MusicLibrary.Records do
limit = Keyword.get(opts, :limit, 20)
offset = Keyword.get(opts, :offset, 0)
q =
from r in Record,
where: like(r.title, ^"%#{query}%") or like(r.artists, ^"%#{query}%"),
order_by: [r.artists[0]["sort_name"], r.title],
limit: ^limit,
offset: ^offset,
select: ^@fields
search =
query
|> build_search()
|> limit(^limit)
|> offset(^offset)
|> select(^@fields)
Repo.all(q)
Repo.all(search)
end
def search_records_count(query) do
search = build_search(query)
Repo.aggregate(search, :count)
end
defp build_search(query) do
{:ok, parsed_query} = SearchParser.parse(query)
base_search =
from r in Record,
order_by: [r.artists[0]["sort_name"], r.title]
Enum.reduce(parsed_query, base_search, fn
{:artist, artist}, search ->
search |> where([r], like(r.artists, ^"%#{artist}%"))
{:album, album}, search ->
search |> where([r], like(r.title, ^"%#{album}%"))
{:mbid, mbid}, search ->
search |> where([r], r.musicbrainz_id == ^mbid)
{:query, raw_query}, search ->
search
|> where(
[r],
like(r.title, ^"%#{raw_query}%") or like(r.artists, ^"%#{raw_query}%")
)
end)
end
def count_records do
@@ -48,14 +79,6 @@ defmodule MusicLibrary.Records do
Repo.all(q)
end
def search_records_count(query) do
q =
from r in Record,
where: like(r.title, ^"%#{query}%") or like(r.artists, ^"%#{query}%")
Repo.aggregate(q, :count)
end
def get_record!(id), do: Repo.get!(Record, id)
def get_latest_record! do
+5 -1
View File
@@ -28,14 +28,18 @@ defmodule MusicLibrary.Records.SearchParser do
Parse a search query.
iex> MusicLibrary.Records.SearchParser.parse("")
{:ok, %{}}
{:ok, %{query: ""}}
iex> MusicLibrary.Records.SearchParser.parse("marbles")
{:ok, %{query: "marbles"}}
iex> MusicLibrary.Records.SearchParser.parse("artist:marillion album:marbles")
{:ok, %{artist: "marillion", album: "marbles"}}
iex> MusicLibrary.Records.SearchParser.parse("artist:marillion album:fugazi artist:fish")
{:ok, %{artist: "marillion fish", album: "fugazi"}}
iex> MusicLibrary.Records.SearchParser.parse(~s(artist:"the pineapple thief" wilderness))
{:ok, %{artist: "the pineapple thief", query: "wilderness"}}
"""
def parse(""), do: {:ok, %{query: ""}}
def parse(query) do
{:ok, result, _rest, _context, _line, _byte_offset} = search_parser(query)
{:ok, normalize(result)}