feat: MBID search functionality for albums, artists and songs (#4286)

* feat(subsonic): search by MBID functionality

Updated the search methods in the mediaFileRepository, albumRepository, and artistRepository to support searching by MBID in addition to the existing query methods. This change improves the efficiency of media file, album, and artist searches, allowing for faster retrieval of records based on MBID.

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(subsonic): enhance MBID search functionality for albums and artists

Updated the search functionality to support searching by MBID for both
albums and artists. The fullTextFilter function was modified to accept
additional MBID fields, allowing for more comprehensive searches. New
tests were added to ensure that the search functionality correctly
handles MBID queries, including cases for missing entries and the
includeMissing parameter. This enhancement improves the overall search
capabilities of the application, making it easier for users to find
specific media items by their unique identifiers.

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(subsonic): normalize MBID to lowercase for consistent querying

Updated the MBID handling in the SQL search logic to convert the input
to lowercase before executing the query. This change ensures that
searches are case-insensitive, improving the accuracy and reliability
of the search results when querying by MBID.

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan Quintão
2025-06-30 17:11:54 -04:00
committed by GitHub
parent f9c7cc5348
commit bfa5b29913
9 changed files with 438 additions and 22 deletions
+65
View File
@@ -404,4 +404,69 @@ var _ = Describe("ArtistRepository", func() {
Expect(roleFilter("", "artist') SELECT LIKE(CHAR(65,66,67,68,69,70,71),UPPER(HEX(RANDOMBLOB(500000000/2))))--")).To(Equal(squirrel.Eq{"1": 2}))
})
})
Context("MBID Search", func() {
var artistWithMBID model.Artist
var raw *artistRepository
BeforeEach(func() {
raw = repo.(*artistRepository)
// Create a test artist with MBID
artistWithMBID = model.Artist{
ID: "test-mbid-artist",
Name: "Test MBID Artist",
MbzArtistID: "550e8400-e29b-41d4-a716-446655440010", // Valid UUID v4
}
// Insert the test artist into the database
err := repo.Put(&artistWithMBID)
Expect(err).ToNot(HaveOccurred())
})
AfterEach(func() {
// Clean up test data using direct SQL
_, _ = raw.executeSQL(squirrel.Delete(raw.tableName).Where(squirrel.Eq{"id": artistWithMBID.ID}))
})
It("finds artist by mbz_artist_id", func() {
results, err := repo.Search("550e8400-e29b-41d4-a716-446655440010", 0, 10, false)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(HaveLen(1))
Expect(results[0].ID).To(Equal("test-mbid-artist"))
Expect(results[0].Name).To(Equal("Test MBID Artist"))
})
It("returns empty result when MBID is not found", func() {
results, err := repo.Search("550e8400-e29b-41d4-a716-446655440099", 0, 10, false)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(BeEmpty())
})
It("handles includeMissing parameter for MBID search", func() {
// Create a missing artist with MBID
missingArtist := model.Artist{
ID: "test-missing-mbid-artist",
Name: "Test Missing MBID Artist",
MbzArtistID: "550e8400-e29b-41d4-a716-446655440012",
Missing: true,
}
err := repo.Put(&missingArtist)
Expect(err).ToNot(HaveOccurred())
// Should not find missing artist when includeMissing is false
results, err := repo.Search("550e8400-e29b-41d4-a716-446655440012", 0, 10, false)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(BeEmpty())
// Should find missing artist when includeMissing is true
results, err = repo.Search("550e8400-e29b-41d4-a716-446655440012", 0, 10, true)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(HaveLen(1))
Expect(results[0].ID).To(Equal("test-missing-mbid-artist"))
// Clean up
_, _ = raw.executeSQL(squirrel.Delete(raw.tableName).Where(squirrel.Eq{"id": missingArtist.ID}))
})
})
})