@@ -75,6 +75,47 @@ defmodule MusicLibrary.Artists do
|
||||
|> Enum.into(%{})
|
||||
end
|
||||
|
||||
@spec search_by_name(String.t(), non_neg_integer()) :: [map()]
|
||||
def search_by_name(query, limit) do
|
||||
case String.trim(query) do
|
||||
"" ->
|
||||
[]
|
||||
|
||||
trimmed_query ->
|
||||
normalized_query = String.downcase(trimmed_query)
|
||||
|
||||
from(ar in ArtistRecord,
|
||||
join: ai in ArtistInfo,
|
||||
on: ar.musicbrainz_id == ai.id,
|
||||
where:
|
||||
fragment("lower(unaccent(artist ->> '$.name')) LIKE ?", ^"%#{normalized_query}%"),
|
||||
group_by: ar.musicbrainz_id,
|
||||
select: %{artist: ar.artist, image_data_hash: ai.image_data_hash},
|
||||
limit: ^limit,
|
||||
order_by: fragment("artist ->> '$.name'")
|
||||
)
|
||||
|> Repo.all()
|
||||
end
|
||||
end
|
||||
|
||||
@spec search_by_name_count(String.t()) :: non_neg_integer()
|
||||
def search_by_name_count(query) do
|
||||
case String.trim(query) do
|
||||
"" ->
|
||||
0
|
||||
|
||||
trimmed_query ->
|
||||
normalized_query = String.downcase(trimmed_query)
|
||||
|
||||
from(ar in ArtistRecord,
|
||||
where: fragment("lower(artist ->> '$.name') LIKE ?", ^"%#{normalized_query}%"),
|
||||
select: ar.musicbrainz_id,
|
||||
distinct: true
|
||||
)
|
||||
|> Repo.aggregate(:count, :musicbrainz_id)
|
||||
end
|
||||
end
|
||||
|
||||
@spec exists?(String.t()) :: boolean()
|
||||
def exists?(artist_id) do
|
||||
q =
|
||||
|
||||
@@ -8,11 +8,7 @@ defmodule MusicLibrary.Search do
|
||||
- Artists
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
|
||||
alias MusicLibrary.Artists.ArtistInfo
|
||||
alias MusicLibrary.{Collection, RecordSets, Repo, Wishlist}
|
||||
alias MusicLibrary.Records.ArtistRecord
|
||||
alias MusicLibrary.{Artists, Collection, RecordSets, Wishlist}
|
||||
|
||||
@pagination Application.compile_env!(:music_library, :pagination)
|
||||
|
||||
@@ -62,26 +58,7 @@ defmodule MusicLibrary.Search do
|
||||
"""
|
||||
@spec search_artists(String.t(), non_neg_integer()) :: [map()]
|
||||
def search_artists(query, limit \\ @pagination[:search_preview_limit]) do
|
||||
case String.trim(query) do
|
||||
"" ->
|
||||
[]
|
||||
|
||||
trimmed_query ->
|
||||
normalized_query = String.downcase(trimmed_query)
|
||||
|
||||
q =
|
||||
from ar in ArtistRecord,
|
||||
join: ai in ArtistInfo,
|
||||
on: ar.musicbrainz_id == ai.id,
|
||||
where:
|
||||
fragment("lower(unaccent(artist ->> '$.name')) LIKE ?", ^"%#{normalized_query}%"),
|
||||
group_by: ar.musicbrainz_id,
|
||||
select: %{artist: ar.artist, image_data_hash: ai.image_data_hash},
|
||||
limit: ^limit,
|
||||
order_by: fragment("artist ->> '$.name'")
|
||||
|
||||
Repo.all(q)
|
||||
end
|
||||
Artists.search_by_name(query, limit)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -115,25 +92,6 @@ defmodule MusicLibrary.Search do
|
||||
"""
|
||||
@spec search_artists_count(String.t()) :: non_neg_integer()
|
||||
def search_artists_count(query) do
|
||||
case String.trim(query) do
|
||||
"" ->
|
||||
0
|
||||
|
||||
trimmed_query ->
|
||||
normalized_query = String.downcase(trimmed_query)
|
||||
|
||||
# Use a subquery to count distinct musicbrainz_ids
|
||||
subquery =
|
||||
from ar in ArtistRecord,
|
||||
where: fragment("lower(artist ->> '$.name') LIKE ?", ^"%#{normalized_query}%"),
|
||||
select: ar.musicbrainz_id,
|
||||
distinct: true
|
||||
|
||||
q =
|
||||
from s in subquery(subquery),
|
||||
select: count()
|
||||
|
||||
Repo.one(q) || 0
|
||||
end
|
||||
Artists.search_by_name_count(query)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,6 +31,57 @@ defmodule MusicLibrary.ArtistsTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "search_by_name/2" do
|
||||
test "returns artists matching the query" do
|
||||
record = record_with_artist("Marillion")
|
||||
[artist] = record.artists
|
||||
artist_info(artist.musicbrainz_id)
|
||||
|
||||
results = Artists.search_by_name("Marillion", 10)
|
||||
|
||||
assert length(results) == 1
|
||||
assert hd(results).artist.name == "Marillion"
|
||||
end
|
||||
|
||||
test "returns empty list for empty query" do
|
||||
assert Artists.search_by_name("", 10) == []
|
||||
assert Artists.search_by_name(" ", 10) == []
|
||||
end
|
||||
|
||||
test "respects limit" do
|
||||
for name <- ["Marillion", "Steven Wilson"] do
|
||||
record = record_with_artist(name)
|
||||
[artist] = record.artists
|
||||
artist_info(artist.musicbrainz_id)
|
||||
end
|
||||
|
||||
results = Artists.search_by_name("i", 1)
|
||||
|
||||
assert length(results) == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "search_by_name_count/1" do
|
||||
test "returns count of matching artists" do
|
||||
record = record_with_artist("Marillion")
|
||||
_other = record_with_artist("Marillion")
|
||||
|
||||
[artist] = record.artists
|
||||
artist_info(artist.musicbrainz_id)
|
||||
|
||||
assert Artists.search_by_name_count("Marillion") == 1
|
||||
end
|
||||
|
||||
test "returns 0 for empty query" do
|
||||
assert Artists.search_by_name_count("") == 0
|
||||
assert Artists.search_by_name_count(" ") == 0
|
||||
end
|
||||
|
||||
test "returns 0 for no matches" do
|
||||
assert Artists.search_by_name_count("zzz_nonexistent_zzz") == 0
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch_artist_info/1" do
|
||||
test "it stores musicbrainz and discogs data" do
|
||||
steven_wilson_musicbrainz_id = "3a51b862-0144-40f6-aa17-6aaeefea29d9"
|
||||
|
||||
Reference in New Issue
Block a user