schema.sql 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 provider_creator_raw_cache (
  41. id BIGSERIAL PRIMARY KEY,
  42. provider TEXT NOT NULL,
  43. endpoint TEXT NOT NULL,
  44. request_params JSONB NOT NULL DEFAULT '{}'::jsonb,
  45. platform TEXT NOT NULL,
  46. platform_user_id TEXT NOT NULL,
  47. display_name TEXT NOT NULL DEFAULT '',
  48. fans_count BIGINT DEFAULT 0,
  49. liked_collect_count BIGINT DEFAULT 0,
  50. content_type TEXT,
  51. content_tags JSONB DEFAULT '[]'::jsonb,
  52. persona_tags JSONB DEFAULT '[]'::jsonb,
  53. city TEXT,
  54. geo_location TEXT,
  55. profile_url TEXT,
  56. cooperation_method TEXT,
  57. image_price INTEGER DEFAULT 0,
  58. video_price INTEGER DEFAULT 0,
  59. min_price INTEGER DEFAULT 0,
  60. cooperation_status TEXT,
  61. raw_creator JSONB NOT NULL DEFAULT '{}'::jsonb,
  62. fetched_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  63. expires_at TIMESTAMPTZ NOT NULL DEFAULT now() + interval '30 days',
  64. normalized_status TEXT NOT NULL DEFAULT 'raw',
  65. embedding_text TEXT NOT NULL DEFAULT '',
  66. embedding DOUBLE PRECISION[] NOT NULL DEFAULT '{}',
  67. UNIQUE(provider, platform, platform_user_id)
  68. );
  69. CREATE TABLE IF NOT EXISTS creator_retrieval_event (
  70. id BIGSERIAL PRIMARY KEY,
  71. task_id TEXT,
  72. query_text TEXT NOT NULL DEFAULT '',
  73. criteria JSONB NOT NULL DEFAULT '{}'::jsonb,
  74. local_hit_count INTEGER NOT NULL DEFAULT 0,
  75. provider_hit_count INTEGER NOT NULL DEFAULT 0,
  76. final_count INTEGER NOT NULL DEFAULT 0,
  77. created_at TIMESTAMPTZ NOT NULL DEFAULT now()
  78. );
  79. CREATE INDEX IF NOT EXISTS idx_creator_clean_platform ON creator_profile_clean(platform);
  80. CREATE INDEX IF NOT EXISTS idx_creator_clean_city ON creator_profile_clean(city);
  81. CREATE INDEX IF NOT EXISTS idx_creator_clean_updated_at ON creator_profile_clean(updated_at);
  82. CREATE INDEX IF NOT EXISTS idx_creator_clean_content_tags ON creator_profile_clean USING GIN(content_tags);
  83. CREATE INDEX IF NOT EXISTS idx_provider_raw_provider_time ON provider_raw_cache(provider, fetched_at DESC);
  84. CREATE INDEX IF NOT EXISTS idx_provider_raw_expires_at ON provider_raw_cache(expires_at);
  85. CREATE INDEX IF NOT EXISTS idx_provider_raw_request_params ON provider_raw_cache USING GIN(request_params);
  86. CREATE INDEX IF NOT EXISTS idx_provider_creator_raw_platform ON provider_creator_raw_cache(platform);
  87. CREATE INDEX IF NOT EXISTS idx_provider_creator_raw_city ON provider_creator_raw_cache(city);
  88. CREATE INDEX IF NOT EXISTS idx_provider_creator_raw_expires_at ON provider_creator_raw_cache(expires_at);
  89. CREATE INDEX IF NOT EXISTS idx_provider_creator_raw_content_tags ON provider_creator_raw_cache USING GIN(content_tags);
  90. CREATE OR REPLACE VIEW creator_profile_retrieval_view AS
  91. SELECT
  92. 'clean'::text AS cache_layer,
  93. source_provider,
  94. platform,
  95. platform_user_id,
  96. display_name,
  97. fans_count,
  98. liked_collect_count,
  99. content_type,
  100. content_tags,
  101. persona_tags,
  102. city,
  103. geo_location,
  104. profile_url,
  105. cooperation_method,
  106. image_price,
  107. video_price,
  108. min_price,
  109. cooperation_status,
  110. updated_at AS cached_at,
  111. NULL::timestamptz AS expires_at
  112. FROM creator_profile_clean
  113. UNION ALL
  114. SELECT
  115. 'provider_raw'::text AS cache_layer,
  116. provider AS source_provider,
  117. platform,
  118. platform_user_id,
  119. display_name,
  120. fans_count,
  121. liked_collect_count,
  122. content_type,
  123. content_tags,
  124. persona_tags,
  125. city,
  126. geo_location,
  127. profile_url,
  128. cooperation_method,
  129. image_price,
  130. video_price,
  131. min_price,
  132. cooperation_status,
  133. fetched_at AS cached_at,
  134. expires_at
  135. FROM provider_creator_raw_cache
  136. WHERE expires_at > now();
  137. CREATE OR REPLACE FUNCTION cosine_similarity(a DOUBLE PRECISION[], b DOUBLE PRECISION[])
  138. RETURNS DOUBLE PRECISION
  139. LANGUAGE SQL
  140. IMMUTABLE
  141. AS $$
  142. WITH pairs AS (
  143. SELECT
  144. av.val AS av,
  145. bv.val AS bv
  146. FROM unnest(a) WITH ORDINALITY AS av(val, idx)
  147. JOIN unnest(b) WITH ORDINALITY AS bv(val, idx)
  148. ON av.idx = bv.idx
  149. ),
  150. sums AS (
  151. SELECT
  152. SUM(av * bv) AS dot,
  153. SQRT(SUM(av * av)) AS norm_a,
  154. SQRT(SUM(bv * bv)) AS norm_b
  155. FROM pairs
  156. )
  157. SELECT CASE
  158. WHEN norm_a = 0 OR norm_b = 0 OR norm_a IS NULL OR norm_b IS NULL THEN 0
  159. ELSE dot / (norm_a * norm_b)
  160. END
  161. FROM sums;
  162. $$;