schema.sql 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. CREATE TABLE IF NOT EXISTS creator_profile_clean (
  2. id BIGSERIAL PRIMARY KEY,
  3. platform TEXT NOT NULL,
  4. platform_user_id TEXT NOT NULL,
  5. display_name TEXT NOT NULL,
  6. gender TEXT,
  7. fans_count BIGINT DEFAULT 0,
  8. liked_collect_count BIGINT DEFAULT 0,
  9. content_type TEXT,
  10. content_tags JSONB DEFAULT '[]'::jsonb,
  11. persona_tags JSONB DEFAULT '[]'::jsonb,
  12. city TEXT,
  13. geo_location TEXT,
  14. profile_url TEXT,
  15. cooperation_method TEXT,
  16. image_price INTEGER DEFAULT 0,
  17. video_price INTEGER DEFAULT 0,
  18. min_price INTEGER DEFAULT 0,
  19. cooperation_status TEXT,
  20. source_kind TEXT NOT NULL DEFAULT 'uploaded',
  21. source_provider TEXT NOT NULL DEFAULT 'local-upload',
  22. source_file TEXT,
  23. source_confidence INTEGER DEFAULT 90,
  24. updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  25. embedding_text TEXT NOT NULL DEFAULT '',
  26. embedding DOUBLE PRECISION[] NOT NULL DEFAULT '{}',
  27. UNIQUE(platform, platform_user_id)
  28. );
  29. CREATE TABLE IF NOT EXISTS provider_raw_cache (
  30. id BIGSERIAL PRIMARY KEY,
  31. provider TEXT NOT NULL,
  32. endpoint TEXT NOT NULL,
  33. request_params JSONB NOT NULL DEFAULT '{}'::jsonb,
  34. response_body JSONB NOT NULL DEFAULT '{}'::jsonb,
  35. fetched_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  36. expires_at TIMESTAMPTZ NOT NULL DEFAULT now() + interval '30 days',
  37. normalized_status TEXT NOT NULL DEFAULT 'pending',
  38. archive_path TEXT
  39. );
  40. CREATE TABLE IF NOT EXISTS creator_retrieval_event (
  41. id BIGSERIAL PRIMARY KEY,
  42. task_id TEXT,
  43. query_text TEXT NOT NULL DEFAULT '',
  44. criteria JSONB NOT NULL DEFAULT '{}'::jsonb,
  45. local_hit_count INTEGER NOT NULL DEFAULT 0,
  46. provider_hit_count INTEGER NOT NULL DEFAULT 0,
  47. final_count INTEGER NOT NULL DEFAULT 0,
  48. created_at TIMESTAMPTZ NOT NULL DEFAULT now()
  49. );
  50. CREATE INDEX IF NOT EXISTS idx_creator_clean_platform ON creator_profile_clean(platform);
  51. CREATE INDEX IF NOT EXISTS idx_creator_clean_city ON creator_profile_clean(city);
  52. CREATE INDEX IF NOT EXISTS idx_creator_clean_updated_at ON creator_profile_clean(updated_at);
  53. CREATE INDEX IF NOT EXISTS idx_creator_clean_content_tags ON creator_profile_clean USING GIN(content_tags);
  54. CREATE INDEX IF NOT EXISTS idx_provider_raw_provider_time ON provider_raw_cache(provider, fetched_at DESC);
  55. CREATE INDEX IF NOT EXISTS idx_provider_raw_expires_at ON provider_raw_cache(expires_at);
  56. CREATE INDEX IF NOT EXISTS idx_provider_raw_request_params ON provider_raw_cache USING GIN(request_params);
  57. CREATE OR REPLACE FUNCTION cosine_similarity(a DOUBLE PRECISION[], b DOUBLE PRECISION[])
  58. RETURNS DOUBLE PRECISION
  59. LANGUAGE SQL
  60. IMMUTABLE
  61. AS $$
  62. WITH pairs AS (
  63. SELECT
  64. av.val AS av,
  65. bv.val AS bv
  66. FROM unnest(a) WITH ORDINALITY AS av(val, idx)
  67. JOIN unnest(b) WITH ORDINALITY AS bv(val, idx)
  68. ON av.idx = bv.idx
  69. ),
  70. sums AS (
  71. SELECT
  72. SUM(av * bv) AS dot,
  73. SQRT(SUM(av * av)) AS norm_a,
  74. SQRT(SUM(bv * bv)) AS norm_b
  75. FROM pairs
  76. )
  77. SELECT CASE
  78. WHEN norm_a = 0 OR norm_b = 0 OR norm_a IS NULL OR norm_b IS NULL THEN 0
  79. ELSE dot / (norm_a * norm_b)
  80. END
  81. FROM sums;
  82. $$;