refactor(monitoring/citations): consolidate domain mapping via CTE
Replace the per-row tenant+global LATERAL joins with a single CTE that materializes filtered citations and resolves domain mappings once per distinct host/domain/site_key triple. Reduces redundant scans of site_domain_mappings on large run batches.
This commit is contained in:
@@ -2791,50 +2791,75 @@ func (s *MonitoringService) loadCitationsForRuns(ctx context.Context, tenantID i
|
|||||||
}
|
}
|
||||||
|
|
||||||
rows, err := s.monitoringPool.Query(ctx, `
|
rows, err := s.monitoringPool.Query(ctx, `
|
||||||
|
WITH filtered_citations AS (
|
||||||
|
SELECT
|
||||||
|
cf.id,
|
||||||
|
cf.run_id,
|
||||||
|
cf.cited_url,
|
||||||
|
cf.cited_title,
|
||||||
|
cf.host,
|
||||||
|
cf.registrable_domain,
|
||||||
|
cf.site_key,
|
||||||
|
cf.article_id,
|
||||||
|
cf.resolution_status,
|
||||||
|
cf.resolution_confidence
|
||||||
|
FROM monitoring_citation_facts cf
|
||||||
|
WHERE cf.tenant_id = $1
|
||||||
|
AND cf.run_id = ANY($2)
|
||||||
|
),
|
||||||
|
domain_keys AS (
|
||||||
|
SELECT DISTINCT host, registrable_domain, site_key
|
||||||
|
FROM filtered_citations
|
||||||
|
),
|
||||||
|
domain_mappings AS (
|
||||||
|
SELECT
|
||||||
|
dk.host,
|
||||||
|
dk.registrable_domain,
|
||||||
|
dk.site_key,
|
||||||
|
dm.registrable_domain AS mapped_domain,
|
||||||
|
dm.site_key AS mapped_site_key,
|
||||||
|
dm.site_name AS mapped_site_name
|
||||||
|
FROM domain_keys dk
|
||||||
|
LEFT JOIN LATERAL (
|
||||||
|
SELECT mapping.registrable_domain, mapping.site_key, mapping.site_name
|
||||||
|
FROM site_domain_mappings mapping
|
||||||
|
WHERE mapping.is_active = TRUE
|
||||||
|
AND mapping.registrable_domain = ANY(
|
||||||
|
ARRAY(
|
||||||
|
SELECT DISTINCT candidate
|
||||||
|
FROM (
|
||||||
|
VALUES (dk.registrable_domain), (dk.site_key), (dk.host)
|
||||||
|
UNION ALL
|
||||||
|
SELECT array_to_string(host_parts.value[idx.value:array_length(host_parts.value, 1)], '.')
|
||||||
|
FROM (SELECT string_to_array(dk.host, '.') AS value) host_parts
|
||||||
|
CROSS JOIN generate_subscripts(host_parts.value, 1) AS idx(value)
|
||||||
|
WHERE idx.value > 1
|
||||||
|
) candidates(candidate)
|
||||||
|
WHERE candidate IS NOT NULL AND candidate <> ''
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ORDER BY LENGTH(mapping.registrable_domain) DESC, mapping.id DESC
|
||||||
|
LIMIT 1
|
||||||
|
) dm ON TRUE
|
||||||
|
)
|
||||||
SELECT
|
SELECT
|
||||||
cf.run_id,
|
fc.run_id,
|
||||||
cf.cited_url,
|
fc.cited_url,
|
||||||
cf.cited_title,
|
fc.cited_title,
|
||||||
COALESCE(tm.site_name, gm.site_name, cf.site_key, cf.registrable_domain) AS site_name,
|
COALESCE(dm.mapped_site_name, fc.site_key, fc.registrable_domain) AS site_name,
|
||||||
COALESCE(tm.site_key, gm.site_key, cf.site_key) AS site_key,
|
COALESCE(dm.mapped_site_key, fc.site_key) AS site_key,
|
||||||
cf.article_id,
|
fc.article_id,
|
||||||
alias.article_title_snapshot AS article_title,
|
alias.article_title_snapshot AS article_title,
|
||||||
cf.resolution_status,
|
fc.resolution_status,
|
||||||
cf.resolution_confidence
|
fc.resolution_confidence
|
||||||
FROM monitoring_citation_facts cf
|
FROM filtered_citations fc
|
||||||
LEFT JOIN LATERAL (
|
LEFT JOIN domain_mappings dm
|
||||||
SELECT site_key, site_name
|
ON dm.host = fc.host
|
||||||
FROM site_domain_mappings
|
AND dm.registrable_domain = fc.registrable_domain
|
||||||
WHERE tenant_id = cf.tenant_id
|
AND dm.site_key = fc.site_key
|
||||||
AND is_active = TRUE
|
|
||||||
AND (
|
|
||||||
registrable_domain = cf.registrable_domain
|
|
||||||
OR registrable_domain = cf.site_key
|
|
||||||
OR cf.host = registrable_domain
|
|
||||||
OR cf.host LIKE '%.' || registrable_domain
|
|
||||||
)
|
|
||||||
ORDER BY LENGTH(registrable_domain) DESC, id DESC
|
|
||||||
LIMIT 1
|
|
||||||
) tm ON TRUE
|
|
||||||
LEFT JOIN LATERAL (
|
|
||||||
SELECT site_key, site_name
|
|
||||||
FROM site_domain_mappings
|
|
||||||
WHERE tenant_id IS NULL
|
|
||||||
AND is_active = TRUE
|
|
||||||
AND (
|
|
||||||
registrable_domain = cf.registrable_domain
|
|
||||||
OR registrable_domain = cf.site_key
|
|
||||||
OR cf.host = registrable_domain
|
|
||||||
OR cf.host LIKE '%.' || registrable_domain
|
|
||||||
)
|
|
||||||
ORDER BY LENGTH(registrable_domain) DESC, id DESC
|
|
||||||
LIMIT 1
|
|
||||||
) gm ON tm.site_key IS NULL
|
|
||||||
LEFT JOIN monitoring_article_url_aliases alias
|
LEFT JOIN monitoring_article_url_aliases alias
|
||||||
ON alias.tenant_id = cf.tenant_id AND alias.article_id = cf.article_id
|
ON alias.tenant_id = $1 AND alias.article_id = fc.article_id
|
||||||
WHERE cf.tenant_id = $1
|
ORDER BY fc.run_id ASC, fc.id ASC
|
||||||
AND cf.run_id = ANY($2)
|
|
||||||
ORDER BY cf.run_id ASC, cf.id ASC
|
|
||||||
`, tenantID, runIDs)
|
`, tenantID, runIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, response.ErrInternal(50041, "query_failed", "failed to load citations")
|
return nil, response.ErrInternal(50041, "query_failed", "failed to load citations")
|
||||||
@@ -2881,45 +2906,17 @@ func (s *MonitoringService) loadQuestionCitationAnalysis(ctx context.Context, te
|
|||||||
platformQueryIDs := monitoringPlatformQueryIDs(aiPlatformID)
|
platformQueryIDs := monitoringPlatformQueryIDs(aiPlatformID)
|
||||||
|
|
||||||
rows, err := s.monitoringPool.Query(ctx, `
|
rows, err := s.monitoringPool.Query(ctx, `
|
||||||
WITH grouped AS (
|
WITH filtered_facts AS (
|
||||||
SELECT
|
SELECT
|
||||||
r.ai_platform_id,
|
r.ai_platform_id,
|
||||||
COALESCE(tm.site_name, gm.site_name, cf.site_key, cf.registrable_domain) AS site_name,
|
cf.id,
|
||||||
COALESCE(tm.site_key, gm.site_key, cf.site_key) AS site_key,
|
cf.host,
|
||||||
COALESCE(tm.registrable_domain, gm.registrable_domain, cf.site_key, cf.registrable_domain) AS site_domain,
|
cf.registrable_domain,
|
||||||
COUNT(cf.id) AS citation_count,
|
cf.site_key,
|
||||||
COUNT(*) FILTER (WHERE cf.article_id IS NOT NULL AND r.ai_platform_id <> 'qwen') AS content_citation_count
|
cf.article_id
|
||||||
FROM question_monitor_runs r
|
FROM question_monitor_runs r
|
||||||
JOIN monitoring_citation_facts cf
|
JOIN monitoring_citation_facts cf
|
||||||
ON cf.tenant_id = r.tenant_id AND cf.run_id = r.id
|
ON cf.tenant_id = r.tenant_id AND cf.run_id = r.id
|
||||||
LEFT JOIN LATERAL (
|
|
||||||
SELECT registrable_domain, site_key, site_name
|
|
||||||
FROM site_domain_mappings
|
|
||||||
WHERE tenant_id = cf.tenant_id
|
|
||||||
AND is_active = TRUE
|
|
||||||
AND (
|
|
||||||
registrable_domain = cf.registrable_domain
|
|
||||||
OR registrable_domain = cf.site_key
|
|
||||||
OR cf.host = registrable_domain
|
|
||||||
OR cf.host LIKE '%.' || registrable_domain
|
|
||||||
)
|
|
||||||
ORDER BY LENGTH(registrable_domain) DESC, id DESC
|
|
||||||
LIMIT 1
|
|
||||||
) tm ON TRUE
|
|
||||||
LEFT JOIN LATERAL (
|
|
||||||
SELECT registrable_domain, site_key, site_name
|
|
||||||
FROM site_domain_mappings
|
|
||||||
WHERE tenant_id IS NULL
|
|
||||||
AND is_active = TRUE
|
|
||||||
AND (
|
|
||||||
registrable_domain = cf.registrable_domain
|
|
||||||
OR registrable_domain = cf.site_key
|
|
||||||
OR cf.host = registrable_domain
|
|
||||||
OR cf.host LIKE '%.' || registrable_domain
|
|
||||||
)
|
|
||||||
ORDER BY LENGTH(registrable_domain) DESC, id DESC
|
|
||||||
LIMIT 1
|
|
||||||
) gm ON tm.site_key IS NULL
|
|
||||||
WHERE r.tenant_id = $1
|
WHERE r.tenant_id = $1
|
||||||
AND r.brand_id = $2
|
AND r.brand_id = $2
|
||||||
AND r.question_id = $3
|
AND r.question_id = $3
|
||||||
@@ -2928,11 +2925,60 @@ func (s *MonitoringService) loadQuestionCitationAnalysis(ctx context.Context, te
|
|||||||
AND r.status = 'succeeded'
|
AND r.status = 'succeeded'
|
||||||
AND r.business_date BETWEEN $6::date AND $7::date
|
AND r.business_date BETWEEN $6::date AND $7::date
|
||||||
AND ($8::text[] IS NULL OR r.ai_platform_id = ANY($8))
|
AND ($8::text[] IS NULL OR r.ai_platform_id = ANY($8))
|
||||||
|
),
|
||||||
|
domain_keys AS (
|
||||||
|
SELECT DISTINCT host, registrable_domain, site_key
|
||||||
|
FROM filtered_facts
|
||||||
|
),
|
||||||
|
domain_mappings AS (
|
||||||
|
SELECT
|
||||||
|
dk.host,
|
||||||
|
dk.registrable_domain,
|
||||||
|
dk.site_key,
|
||||||
|
dm.registrable_domain AS mapped_domain,
|
||||||
|
dm.site_key AS mapped_site_key,
|
||||||
|
dm.site_name AS mapped_site_name
|
||||||
|
FROM domain_keys dk
|
||||||
|
LEFT JOIN LATERAL (
|
||||||
|
SELECT mapping.registrable_domain, mapping.site_key, mapping.site_name
|
||||||
|
FROM site_domain_mappings mapping
|
||||||
|
WHERE mapping.is_active = TRUE
|
||||||
|
AND mapping.registrable_domain = ANY(
|
||||||
|
ARRAY(
|
||||||
|
SELECT DISTINCT candidate
|
||||||
|
FROM (
|
||||||
|
VALUES (dk.registrable_domain), (dk.site_key), (dk.host)
|
||||||
|
UNION ALL
|
||||||
|
SELECT array_to_string(host_parts.value[idx.value:array_length(host_parts.value, 1)], '.')
|
||||||
|
FROM (SELECT string_to_array(dk.host, '.') AS value) host_parts
|
||||||
|
CROSS JOIN generate_subscripts(host_parts.value, 1) AS idx(value)
|
||||||
|
WHERE idx.value > 1
|
||||||
|
) candidates(candidate)
|
||||||
|
WHERE candidate IS NOT NULL AND candidate <> ''
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ORDER BY LENGTH(mapping.registrable_domain) DESC, mapping.id DESC
|
||||||
|
LIMIT 1
|
||||||
|
) dm ON TRUE
|
||||||
|
),
|
||||||
|
grouped AS (
|
||||||
|
SELECT
|
||||||
|
ff.ai_platform_id,
|
||||||
|
COALESCE(dm.mapped_site_name, ff.site_key, ff.registrable_domain) AS site_name,
|
||||||
|
COALESCE(dm.mapped_site_key, ff.site_key) AS site_key,
|
||||||
|
COALESCE(dm.mapped_domain, ff.site_key, ff.registrable_domain) AS site_domain,
|
||||||
|
COUNT(ff.id) AS citation_count,
|
||||||
|
COUNT(*) FILTER (WHERE ff.article_id IS NOT NULL AND ff.ai_platform_id <> 'qwen') AS content_citation_count
|
||||||
|
FROM filtered_facts ff
|
||||||
|
LEFT JOIN domain_mappings dm
|
||||||
|
ON dm.host = ff.host
|
||||||
|
AND dm.registrable_domain = ff.registrable_domain
|
||||||
|
AND dm.site_key = ff.site_key
|
||||||
GROUP BY
|
GROUP BY
|
||||||
r.ai_platform_id,
|
ff.ai_platform_id,
|
||||||
COALESCE(tm.site_name, gm.site_name, cf.site_key, cf.registrable_domain),
|
COALESCE(dm.mapped_site_name, ff.site_key, ff.registrable_domain),
|
||||||
COALESCE(tm.site_key, gm.site_key, cf.site_key),
|
COALESCE(dm.mapped_site_key, ff.site_key),
|
||||||
COALESCE(tm.registrable_domain, gm.registrable_domain, cf.site_key, cf.registrable_domain)
|
COALESCE(dm.mapped_domain, ff.site_key, ff.registrable_domain)
|
||||||
),
|
),
|
||||||
totals AS (
|
totals AS (
|
||||||
SELECT
|
SELECT
|
||||||
|
|||||||
Reference in New Issue
Block a user