feat: add monitoring marked articles and retention updates
Frontend CI / Frontend (push) Successful in 7m47s
Backend CI / Backend (push) Successful in 19m26s

This commit is contained in:
2026-06-17 12:48:41 +08:00
parent 9ed857e159
commit 31c4dd9358
40 changed files with 2373 additions and 488 deletions
@@ -0,0 +1,7 @@
DROP INDEX IF EXISTS idx_monitoring_citation_facts_content_source;
ALTER TABLE monitoring_citation_facts
DROP COLUMN IF EXISTS content_source_id,
DROP COLUMN IF EXISTS content_source_type;
DROP TABLE IF EXISTS monitoring_user_marked_articles;
@@ -0,0 +1,41 @@
CREATE TABLE IF NOT EXISTS monitoring_user_marked_articles (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
brand_id BIGINT,
marked_by_user_id BIGINT,
article_title TEXT NOT NULL,
original_url TEXT NOT NULL,
normalized_url TEXT NOT NULL,
host VARCHAR(255) NOT NULL,
registrable_domain VARCHAR(255) NOT NULL,
site_key VARCHAR(255) NOT NULL,
last_path_segment VARCHAR(255),
publish_platform VARCHAR(100) NOT NULL DEFAULT '外部文章',
marked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL DEFAULT (NOW() + INTERVAL '6 months'),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX IF NOT EXISTS uk_monitoring_user_marked_article_url
ON monitoring_user_marked_articles(tenant_id, normalized_url);
CREATE INDEX IF NOT EXISTS idx_monitoring_user_marked_articles_domain
ON monitoring_user_marked_articles(tenant_id, registrable_domain, created_at DESC, id DESC);
CREATE INDEX IF NOT EXISTS idx_monitoring_user_marked_articles_title
ON monitoring_user_marked_articles USING GIN (to_tsvector('simple', article_title));
CREATE INDEX IF NOT EXISTS idx_monitoring_user_marked_articles_created
ON monitoring_user_marked_articles(tenant_id, created_at DESC, id DESC);
CREATE INDEX IF NOT EXISTS idx_monitoring_user_marked_articles_expires
ON monitoring_user_marked_articles(expires_at, id);
ALTER TABLE monitoring_citation_facts
ADD COLUMN IF NOT EXISTS content_source_type VARCHAR(30),
ADD COLUMN IF NOT EXISTS content_source_id BIGINT;
CREATE INDEX IF NOT EXISTS idx_monitoring_citation_facts_content_source
ON monitoring_citation_facts(tenant_id, content_source_type, content_source_id)
WHERE content_source_type IS NOT NULL AND content_source_id IS NOT NULL;
@@ -0,0 +1,5 @@
DROP INDEX IF EXISTS idx_article_url_alias_article_lookup;
DROP INDEX IF EXISTS idx_citation_facts_content_window;
DROP INDEX IF EXISTS idx_citation_facts_normalized_url;
DROP INDEX IF EXISTS idx_citation_facts_tenant_run;
DROP INDEX IF EXISTS idx_monitor_runs_citation_summary;
@@ -0,0 +1,63 @@
CREATE INDEX IF NOT EXISTS idx_monitor_runs_citation_summary
ON question_monitor_runs (
tenant_id,
brand_id,
collector_type,
status,
business_date,
question_id,
ai_platform_id,
id
);
CREATE INDEX IF NOT EXISTS idx_citation_facts_tenant_run
ON monitoring_citation_facts(tenant_id, run_id);
CREATE INDEX IF NOT EXISTS idx_citation_facts_normalized_url
ON monitoring_citation_facts(tenant_id, normalized_url);
CREATE INDEX IF NOT EXISTS idx_citation_facts_content_window
ON monitoring_citation_facts (
tenant_id,
brand_id,
business_date,
ai_platform_id,
content_source_type,
content_source_id,
run_id
)
WHERE content_source_type IS NOT NULL AND content_source_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_article_url_alias_article_lookup
ON monitoring_article_url_aliases(tenant_id, article_id, updated_at DESC, id DESC)
WHERE confidence = 'high';
UPDATE monitoring_citation_facts cf
SET content_source_type = 'published_article',
content_source_id = alias.article_id
FROM monitoring_article_url_aliases alias
WHERE alias.tenant_id = cf.tenant_id
AND alias.normalized_url = cf.normalized_url
AND alias.confidence = 'high'
AND alias.article_id IS NOT NULL
AND (
cf.content_source_type IS DISTINCT FROM 'published_article'
OR cf.content_source_id IS DISTINCT FROM alias.article_id
);
UPDATE monitoring_citation_facts
SET content_source_type = 'published_article',
content_source_id = article_id
WHERE content_source_type IS NULL
AND content_source_id IS NULL
AND article_id IS NOT NULL;
UPDATE monitoring_citation_facts cf
SET content_source_type = 'manual_mark',
content_source_id = marked.id
FROM monitoring_user_marked_articles marked
WHERE marked.tenant_id = cf.tenant_id
AND marked.normalized_url = cf.normalized_url
AND marked.expires_at > NOW()
AND cf.content_source_type IS NULL
AND cf.content_source_id IS NULL;
@@ -0,0 +1,7 @@
DROP INDEX IF EXISTS idx_marked_articles_title_trgm;
DROP INDEX IF EXISTS idx_marked_articles_domain_trgm;
DROP INDEX IF EXISTS idx_citation_facts_day_content_run;
DROP INDEX IF EXISTS idx_citation_facts_run_content;
CREATE INDEX IF NOT EXISTS idx_monitoring_user_marked_articles_title
ON monitoring_user_marked_articles USING GIN (to_tsvector('simple', article_title));
@@ -0,0 +1,44 @@
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX IF NOT EXISTS idx_citation_facts_run_content
ON monitoring_citation_facts (
tenant_id,
run_id,
content_source_type,
content_source_id
)
WHERE content_source_type IS NOT NULL AND content_source_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_citation_facts_day_content_run
ON monitoring_citation_facts (
tenant_id,
brand_id,
business_date,
ai_platform_id,
run_id,
content_source_type,
content_source_id
)
WHERE content_source_type IS NOT NULL AND content_source_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_marked_articles_domain_trgm
ON monitoring_user_marked_articles
USING GIN (
lower(registrable_domain) gin_trgm_ops,
lower(host) gin_trgm_ops,
lower(site_key) gin_trgm_ops
);
DROP INDEX IF EXISTS idx_monitoring_user_marked_articles_title;
CREATE INDEX IF NOT EXISTS idx_marked_articles_title_trgm
ON monitoring_user_marked_articles
USING GIN (lower(article_title) gin_trgm_ops);
ALTER TABLE monitoring_user_marked_articles
ALTER COLUMN publish_platform SET DEFAULT '外部文章';
UPDATE monitoring_user_marked_articles
SET publish_platform = '外部文章',
updated_at = NOW()
WHERE publish_platform IN ('自有文章', 'Own Article', 'Owned Article', 'Manual Article');
@@ -0,0 +1,10 @@
DROP INDEX IF EXISTS idx_marked_articles_site_key_lookup;
DROP INDEX IF EXISTS idx_marked_articles_host_lookup;
CREATE INDEX IF NOT EXISTS idx_marked_articles_domain_trgm
ON monitoring_user_marked_articles
USING GIN (
lower(registrable_domain) gin_trgm_ops,
lower(host) gin_trgm_ops,
lower(site_key) gin_trgm_ops
);
@@ -0,0 +1,7 @@
DROP INDEX IF EXISTS idx_marked_articles_domain_trgm;
CREATE INDEX IF NOT EXISTS idx_marked_articles_host_lookup
ON monitoring_user_marked_articles(tenant_id, host, created_at DESC, id DESC);
CREATE INDEX IF NOT EXISTS idx_marked_articles_site_key_lookup
ON monitoring_user_marked_articles(tenant_id, site_key, created_at DESC, id DESC);