diff --git a/service_a/internal/domains/meteo/handlers.go b/service_a/internal/domains/meteo/handlers.go index 20213fc..74e5df0 100644 --- a/service_a/internal/domains/meteo/handlers.go +++ b/service_a/internal/domains/meteo/handlers.go @@ -79,6 +79,7 @@ func (h *Handler) IngestExcel(w http.ResponseWriter, r *http.Request) { } func (h *Handler) GetCities(w http.ResponseWriter, r *http.Request) { + h.ToJSON(w, http.StatusOK, app.H{"cities": h.s.GetCities(r.Context())}) } func (h *Handler) GetMeteoData(w http.ResponseWriter, r *http.Request) { diff --git a/service_a/internal/domains/meteo/repository.go b/service_a/internal/domains/meteo/repository.go index d1f6a66..0da4ecc 100644 --- a/service_a/internal/domains/meteo/repository.go +++ b/service_a/internal/domains/meteo/repository.go @@ -11,6 +11,7 @@ import ( type Repository interface { InsertMeteoDataTX(ctx context.Context, params InsertMeteoDataParams) (*InsertMeteoDataResult, error) UpdateBatchElapsedTime(ctx context.Context, batchID int, elapsedMS int) error + GetCities(ctx context.Context) []string GetMeteoData(ctx context.Context, params GetMeteoData) ([]MeteoData, error) } @@ -150,10 +151,32 @@ func (pgx *pgxRepo) UpdateBatchElapsedTime(ctx context.Context, batchID int, ela return nil } -const getMeteoDataQuery = ` +const getCities = `select distinct location_name from public.meteo_data order by location_name` + +func (pgx *pgxRepo) GetCities(ctx context.Context) []string { + rows, err := pgx.Query(ctx, getCities) + if err != nil { + return []string{} + } + defer rows.Close() + + var cities []string + for rows.Next() { + var city string + err := rows.Scan(&city) + if err != nil { + continue + } + cities = append(cities, city) + } + + return cities +} + +const getMeteoData = ` select location_name, date_of_register, max_temp, min_temp, rainfall, cloudiness from public.meteo_data - where location_name = $1 + where location_name_norm = unaccent(lower($1)) and date_of_register >= $2 and date_of_register <= $3 order by date_of_register desc @@ -161,7 +184,7 @@ const getMeteoDataQuery = ` ` func (pgx *pgxRepo) GetMeteoData(ctx context.Context, params GetMeteoData) ([]MeteoData, error) { - rows, err := pgx.Query(ctx, getMeteoDataQuery, params.Location, params.From, params.To, params.Limit, params.Offset) + rows, err := pgx.Query(ctx, getMeteoData, params.Location, params.From, params.To, params.Limit, params.Offset) if err != nil { return nil, fmt.Errorf("error querying meteo data: %w", err) } diff --git a/service_a/internal/domains/meteo/service.go b/service_a/internal/domains/meteo/service.go index 7c64775..2a015e8 100644 --- a/service_a/internal/domains/meteo/service.go +++ b/service_a/internal/domains/meteo/service.go @@ -49,6 +49,10 @@ func (s *Service) UpdateElapsedMS(ctx context.Context, batchID, elapsedMS int) e return nil } +func (s *Service) GetCities(ctx context.Context) []string { + return s.repo.GetCities(ctx) +} + func (s *Service) GetMeteoData(ctx context.Context, params GetMeteoData) ([]MeteoData, error) { return s.repo.GetMeteoData(ctx, params) } diff --git a/service_a/server/database/migrations/001_data.up.sql b/service_a/server/database/migrations/001_data.up.sql index 5572d92..3162843 100644 --- a/service_a/server/database/migrations/001_data.up.sql +++ b/service_a/server/database/migrations/001_data.up.sql @@ -1,4 +1,10 @@ create extension citext; -- noqa +create extension unaccent; + +create or replace function immutable_unaccent(text) +returns text as $$ + select unaccent('unaccent', $1); +$$ language sql immutable; create table public.ingest_batch ( @@ -20,6 +26,7 @@ create table public.meteo_data batch_id int not null references public.ingest_batch (id), location_name citext not null, + location_name_norm text generated always as (immutable_unaccent(lower(location_name))) stored, date_of_register date not null, max_temp numeric(5, 2) not null, min_temp numeric(5, 2) not null, @@ -29,7 +36,7 @@ create table public.meteo_data created_at timestamp not null default now() ); -create index idx_meteo_data_location_name on public.meteo_data (location_name); +create index idx_meteo_data_location_name_norm on public.meteo_data (location_name_norm); create table public.rejected_data (