···133133 return err
134134 }
135135136136+ if _, err := tx.ExecContext(ctx, `
137137+ CREATE INDEX IF NOT EXISTS _idx_feed_words_word ON _feed_words(word, feed_url)
138138+ `); err != nil {
139139+ return err
140140+ }
141141+136142 descInsert := `
137143 INSERT OR IGNORE INTO feed_similarity (feed_a, feed_b, jaccard)
138144 SELECT feed_a, feed_b, 0 FROM _word_overlap
+64-12
internal/cluster/scoring.go
···286286 return err
287287 }
288288289289+ if _, err := tx.ExecContext(ctx, `
290290+ CREATE TEMP TABLE IF NOT EXISTS _user_like_counts (user_did TEXT PRIMARY KEY, cnt INT)
291291+ `); err != nil {
292292+ return err
293293+ }
294294+ if _, err := tx.ExecContext(ctx, `DELETE FROM _user_like_counts`); err != nil {
295295+ return err
296296+ }
297297+ if _, err := tx.ExecContext(ctx, `
298298+ INSERT INTO _user_like_counts SELECT author_did, COUNT(*) FROM likes GROUP BY author_did
299299+ `); err != nil {
300300+ return err
301301+ }
302302+303303+ if _, err := tx.ExecContext(ctx, `
304304+ CREATE TEMP TABLE IF NOT EXISTS _user_tag_counts (user_did TEXT PRIMARY KEY, cnt INT)
305305+ `); err != nil {
306306+ return err
307307+ }
308308+ if _, err := tx.ExecContext(ctx, `DELETE FROM _user_tag_counts`); err != nil {
309309+ return err
310310+ }
311311+ if _, err := tx.ExecContext(ctx, `
312312+ INSERT INTO _user_tag_counts
313313+ WITH user_tags AS (
314314+ SELECT author_did, TRIM(value) AS tag
315315+ FROM annotations, json_each('["' || REPLACE(tags, ',', '","') || '"]')
316316+ WHERE tags IS NOT NULL AND tags != ''
317317+ )
318318+ SELECT author_did, COUNT(DISTINCT tag) FROM user_tags GROUP BY author_did
319319+ `); err != nil {
320320+ return err
321321+ }
322322+323323+ if _, err := tx.ExecContext(ctx, `
324324+ CREATE TEMP TABLE IF NOT EXISTS _user_top_categories (user_did TEXT PRIMARY KEY, categories TEXT)
325325+ `); err != nil {
326326+ return err
327327+ }
328328+ if _, err := tx.ExecContext(ctx, `DELETE FROM _user_top_categories`); err != nil {
329329+ return err
330330+ }
331331+ if _, err := tx.ExecContext(ctx, `
332332+ INSERT INTO _user_top_categories
333333+ SELECT user_did, '[' || GROUP_CONCAT('{"c":"' || category || '","n":"' || CAST(cnt AS TEXT) || '}') || ']'
334334+ FROM (
335335+ SELECT user_did, category, COUNT(*) AS cnt
336336+ FROM subscriptions
337337+ WHERE category IS NOT NULL AND category != ''
338338+ GROUP BY user_did, category
339339+ ORDER BY COUNT(*) DESC
340340+ LIMIT 5
341341+ )
342342+ GROUP BY user_did
343343+ `); err != nil {
344344+ return err
345345+ }
346346+289347 _, err = tx.ExecContext(ctx, `
290348 INSERT INTO user_signal_profiles (user_did, total_likes, total_tags, top_categories)
291349 SELECT
292350 u.did,
293293- (SELECT COUNT(*) FROM likes WHERE author_did = u.did),
294294- COALESCE((SELECT COUNT(DISTINCT TRIM(value))
295295- FROM annotations, json_each('["' || REPLACE(tags, ',', '","') || '"]')
296296- WHERE author_did = u.did AND tags IS NOT NULL AND tags != ''
297297- ), 0),
298298- (SELECT '[' || GROUP_CONCAT('{"c":"' || category || '","n":"' || CAST(cnt AS TEXT) || '}') || ']'
299299- FROM (
300300- SELECT category, COUNT(*) AS cnt
301301- FROM subscriptions WHERE user_did = u.did AND category IS NOT NULL AND category != ''
302302- GROUP BY category ORDER BY cnt DESC LIMIT 5
303303- )
304304- )
351351+ COALESCE(lc.cnt, 0),
352352+ COALESCE(tc.cnt, 0),
353353+ COALESCE(cc.categories, '[]')
305354 FROM users u
355355+ LEFT JOIN _user_like_counts lc ON lc.user_did = u.did
356356+ LEFT JOIN _user_tag_counts tc ON tc.user_did = u.did
357357+ LEFT JOIN _user_top_categories cc ON cc.user_did = u.did
306358 `)
307359 if err != nil {
308360 return err
+5-11
internal/cluster/social.go
···1515 return err
1616 }
17171818- if _, err := tx.ExecContext(ctx, `
1818+ _, err = tx.ExecContext(ctx, `
1919 INSERT INTO follow_distances (user_a, user_b, distance)
2020- SELECT user_did, target_did, 1
2121- FROM follows
2222- WHERE user_did != target_did
2323- `); err != nil {
2424- return err
2525- }
2626-2727- if _, err := tx.ExecContext(ctx, `
2828- INSERT OR IGNORE INTO follow_distances (user_a, user_b, distance)
2020+ SELECT user_did, target_did, 1 FROM follows WHERE user_did != target_did
2121+ UNION ALL
2922 SELECT f1.user_did, f2.target_did, 2
3023 FROM follows f1
3124 JOIN follows f2 ON f1.target_did = f2.user_did
3225 WHERE f1.user_did != f2.target_did
3333- `); err != nil {
2626+ `)
2727+ if err != nil {
3428 return err
3529 }
3630
+3-1
internal/db/db.go
···207207 PRIMARY KEY (account_did, session_id)
208208 )`,
209209 `CREATE INDEX IF NOT EXISTS idx_subscriptions_feed ON subscriptions(feed_url)`,
210210+ `CREATE INDEX IF NOT EXISTS idx_subscriptions_feed_user ON subscriptions(feed_url, user_did)`,
210211 `CREATE INDEX IF NOT EXISTS idx_subscriptions_user ON subscriptions(user_did)`,
211212 `CREATE INDEX IF NOT EXISTS idx_subscriptions_uri ON subscriptions(uri)`,
213213+ `CREATE INDEX IF NOT EXISTS idx_likes_author_feed ON likes(author_did, feed_url, created_at)`,
212214 `CREATE INDEX IF NOT EXISTS idx_articles_feed ON articles(feed_url)`,
213215 `CREATE INDEX IF NOT EXISTS idx_articles_published ON articles(published DESC)`,
214216 `CREATE INDEX IF NOT EXISTS idx_articles_url ON articles(url)`,
···223225 `CREATE INDEX IF NOT EXISTS idx_follows_target ON follows(target_did)`,
224226 `CREATE INDEX IF NOT EXISTS idx_follows_uri ON follows(uri)`,
225227 `CREATE INDEX IF NOT EXISTS idx_user_similarity_b ON user_similarity(user_b)`,
228228+ `CREATE INDEX IF NOT EXISTS idx_user_similarity_a ON user_similarity(user_a)`,
226229227230 `CREATE TABLE IF NOT EXISTS dismissed_recommendations (
228231 user_did TEXT NOT NULL REFERENCES users(did),
···275278 `CREATE INDEX IF NOT EXISTS idx_impressions_last_shown ON recommendation_impressions(last_shown_at)`,
276279 `CREATE INDEX IF NOT EXISTS idx_follow_distances_b ON follow_distances(user_b)`,
277280 `CREATE INDEX IF NOT EXISTS idx_follow_distances_a_dist ON follow_distances(user_a, distance)`,
278278- `CREATE INDEX IF NOT EXISTS idx_likes_author_feed ON likes(author_did, feed_url, created_at)`,
279281 `CREATE INDEX IF NOT EXISTS idx_follows_followed_at ON follows(followed_at)`,
280282 `CREATE INDEX IF NOT EXISTS idx_users_handle ON users(handle)`,
281283 `CREATE VIRTUAL TABLE IF NOT EXISTS articles_fts USING fts5(title, summary, content, author, content=articles, content_rowid=id)`,