- apps/api : API REST Node.js/Fastify + PostgreSQL/PostGIS - apps/geocoder : Worker Python géocodage Nominatim - apps/worker : Scraper Python Metal-Archives - apps/web : Frontend statique Leaflet/clustering/heatmap - infra/ : docker-compose + init.sql Déployé via Coolify + Traefik sur VPS OVH.
42 lines
1.3 KiB
PL/PgSQL
42 lines
1.3 KiB
PL/PgSQL
CREATE EXTENSION IF NOT EXISTS postgis;
|
|
|
|
CREATE TABLE IF NOT EXISTS bands (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
ma_id BIGINT UNIQUE NOT NULL,
|
|
name TEXT NOT NULL,
|
|
country TEXT,
|
|
location_text TEXT,
|
|
status TEXT,
|
|
genre TEXT,
|
|
formed_year INT,
|
|
lat DOUBLE PRECISION,
|
|
lon DOUBLE PRECISION,
|
|
geom GEOGRAPHY(Point, 4326),
|
|
data JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- Keep geom in sync if lat/lon set
|
|
CREATE OR REPLACE FUNCTION bands_set_geom() RETURNS trigger AS $$
|
|
BEGIN
|
|
IF NEW.lat IS NOT NULL AND NEW.lon IS NOT NULL THEN
|
|
NEW.geom := ST_SetSRID(ST_MakePoint(NEW.lon, NEW.lat), 4326)::geography;
|
|
ELSE
|
|
NEW.geom := NULL;
|
|
END IF;
|
|
NEW.updated_at := now();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trg_bands_set_geom ON bands;
|
|
CREATE TRIGGER trg_bands_set_geom
|
|
BEFORE INSERT OR UPDATE OF lat, lon ON bands
|
|
FOR EACH ROW EXECUTE FUNCTION bands_set_geom();
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_bands_country ON bands (country);
|
|
CREATE INDEX IF NOT EXISTS idx_bands_status ON bands (status);
|
|
CREATE INDEX IF NOT EXISTS idx_bands_genre ON bands (genre);
|
|
CREATE INDEX IF NOT EXISTS idx_bands_geom ON bands USING GIST (geom);
|
|
CREATE INDEX IF NOT EXISTS idx_bands_data_gin ON bands USING GIN (data);
|