feat(api): search with Meilisearch (M2)
ci / api / api (push) Successful in 27s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m1s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 34s
ci / ts / ts (packages + web) (push) Successful in 1m1s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 25s
ci / api / api (push) Successful in 27s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m1s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 34s
ci / ts / ts (packages + web) (push) Successful in 1m1s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 25s
- artists, albums and tracks indexes are rebuilt from PostgreSQL next to the live ones and swapped in, so search keeps working; a rebuild runs on start, after every scan and when a source is removed - transliteration fields (Кино ↔ kino) and a retry in the other keyboard layout (ghbdtn → привет) reported as corrected_query - /search/suggest (3 artists, 3 albums, 5 tracks), /search by type with cursor pages, /admin/search/reindex; Meilisearch is part of /readyz - found ids are hydrated from the catalog, so a lagging index never returns deleted entries Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c583991d14
commit
c1160cccd3
16 files changed
+1590
-124
No files matched your search
@@ -189,3 +189,56 @@ func (st *Store) Artist(ctx context.Context, id uuid.UUID) (ArtistRow, error) {
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// AlbumsByIDs — альбомы в порядке ids (недостающие пропускаются).
|
||||
func (st *Store) AlbumsByIDs(ctx context.Context, ids []uuid.UUID) ([]AlbumRow, error) {
|
||||
rows, err := st.pool.Query(ctx, albumSelect+" WHERE al.id = ANY($1)", ids)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("library: albums: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
byID := map[uuid.UUID]AlbumRow{}
|
||||
for rows.Next() {
|
||||
a, err := scanAlbum(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
byID[a.ID] = a
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make([]AlbumRow, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
if a, ok := byID[id]; ok {
|
||||
out = append(out, a)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ArtistsByIDs — исполнители в порядке ids.
|
||||
func (st *Store) ArtistsByIDs(ctx context.Context, ids []uuid.UUID) ([]Ref, error) {
|
||||
rows, err := st.pool.Query(ctx, `SELECT id, name FROM artists WHERE id = ANY($1)`, ids)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("library: artists: %w", err)
|
||||
}
|
||||
refs, err := pgx.CollectRows(rows, func(r pgx.CollectableRow) (Ref, error) {
|
||||
var a Ref
|
||||
return a, r.Scan(&a.ID, &a.Name)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("library: artists: %w", err)
|
||||
}
|
||||
byID := map[uuid.UUID]Ref{}
|
||||
for _, a := range refs {
|
||||
byID[a.ID] = a
|
||||
}
|
||||
out := make([]Ref, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
if a, ok := byID[id]; ok {
|
||||
out = append(out, a)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
Reference in new issue
Block a user