Mejoras: NER, embeddings, dashboard, docker-compose y limpieza

This commit is contained in:
jlimolina 2025-11-17 19:37:05 +01:00
parent 6c5aff9936
commit d508dc2058
19 changed files with 2218 additions and 1185 deletions

View file

@ -0,0 +1,62 @@
-- Función para “normalizar” URLs: minúsculas en esquema/host, quitar www,
-- quitar fragmentos (#...), limpiar trackers comunes (utm_*, gclid, fbclid, ref, etc.),
-- colapsar dobles “/”, y quitar la “/” final salvo si es la raíz.
CREATE OR REPLACE FUNCTION normalize_url(in_url text)
RETURNS text
LANGUAGE plpgsql
AS $$
DECLARE
u text := trim(in_url);
scheme_host text;
path_q text;
BEGIN
IF u IS NULL OR u = '' THEN
RETURN NULL;
END IF;
-- quitar espacios y fragmentos
u := regexp_replace(u, '#.*$', '', 'i');
-- separar esquema+host de path+query
-- ej: https://example.com:443/foo?bar -> scheme_host=https://example.com:443 ; path_q=/foo?bar
scheme_host := substring(u FROM '^[a-z]+://[^/]*');
IF scheme_host IS NULL THEN
-- si no hay esquema, asumimos http
u := 'http://' || u;
scheme_host := substring(u FROM '^[a-z]+://[^/]*');
END IF;
path_q := substring(u FROM '^[a-z]+://[^/]*(/.*)$');
IF path_q IS NULL THEN
path_q := '/';
END IF;
-- normalizar esquema y host (minúsculas, quitar www.)
scheme_host := lower(scheme_host);
scheme_host := regexp_replace(scheme_host, '^(https?://)www\.', '\1', 'i');
-- quitar puerto por defecto (:80 en http, :443 en https)
scheme_host := regexp_replace(scheme_host, '^http://([^/:]+):80$', 'http://\1', 'i');
scheme_host := regexp_replace(scheme_host, '^https://([^/:]+):443$', 'https://\1', 'i');
-- limpiar parámetros de tracking en la query
-- elimina ?utm_... &utm_... gclid fbclid mc_cid mc_eid ref ref_src etc.
path_q := regexp_replace(path_q, '([?&])(utm_[^=&]+|gclid|fbclid|mc_cid|mc_eid|ref|ref_src|yclid|igshid)=[^&#]*', '\1', 'gi');
-- limpiar conectores sobrantes ?, &, &&, ?&, etc.
path_q := regexp_replace(path_q, '\?&+', '?', 'g');
path_q := regexp_replace(path_q, '&{2,}', '&', 'g');
path_q := regexp_replace(path_q, '\?$', '', 'g');
path_q := regexp_replace(path_q, '\?$','', 'g');
-- colapsar dobles barras en path (no tocar “://”)
path_q := regexp_replace(path_q, '/{2,}', '/', 'g');
-- quitar “/” final si no es la raíz
IF path_q <> '/' THEN
path_q := regexp_replace(path_q, '/+$', '', 'g');
END IF;
RETURN scheme_host || path_q;
END;
$$;

View file

@ -0,0 +1,38 @@
-- Añadir columna generada url_norm y crear índice único sobre ella.
-- OJO: si ya existen duplicados, este índice fallará.
-- Primero crea la columna si no existe:
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name='feeds' AND column_name='url_norm'
) THEN
ALTER TABLE feeds
ADD COLUMN url_norm text GENERATED ALWAYS AS (normalize_url(url)) STORED;
END IF;
END $$;
-- Índice único (concurrently para no bloquear). Requiere estar fuera de transacción.
-- Si tu herramienta corre todo en una transacción, ejecuta estas dos líneas aparte.
-- Quita duplicados antes si da error.
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS feeds_url_norm_uniq ON feeds (url_norm)
WHERE url_norm IS NOT NULL;
-- (Opcional) repetir lo mismo para fuentes_url y noticias si quieres esa garantía también:
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name='fuentes_url' AND column_name='url_norm'
) THEN
ALTER TABLE fuentes_url
ADD COLUMN url_norm text GENERATED ALWAYS AS (normalize_url(url)) STORED;
END IF;
END $$;
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS fuentes_url_norm_uniq ON fuentes_url (url_norm)
WHERE url_norm IS NOT NULL;