| @@ -87,27 +87,21 @@ func (e *Engine) GetPeopleRecommendations(ctx context.Context, userDID string, l |
| 87 | return entry, nil | 87 | return entry, nil |
| 88 | } | 88 | } |
| 89 | | 89 | |
| 90 | - recs, err := e.ComputePeopleRecommendationsOnDemand(ctx, userDID, limit*2) | 90 | + half := max(limit/2, 1) |
| | 91 | + |
| | 92 | + inNet, err := e.computePeopleByFollowStatus(ctx, userDID, true, half) |
| 91 | if err != nil { | 93 | if err != nil { |
| 92 | return nil, err | 94 | return nil, err |
| 93 | } | 95 | } |
| 94 | | 96 | |
| 95 | - half := max(limit/2, 1) | 97 | + outNet, err := e.computePeopleByFollowStatus(ctx, userDID, false, half) |
| 96 | - | 98 | + if err != nil { |
| 97 | - var inNet, outNet []*PersonRecommendation | 99 | + return nil, err |
| 98 | - for _, r := range recs { | | |
| 99 | - if r.IsFollowed { | | |
| 100 | - inNet = append(inNet, r) | | |
| 101 | - } else { | | |
| 102 | - outNet = append(outNet, r) | | |
| 103 | - } | | |
| 104 | } | 100 | } |
| 105 | | 101 | |
| 106 | - outTake := min(half, len(outNet)) | 102 | + var recs []*PersonRecommendation |
| 107 | - inTake := min(limit-outTake, len(inNet)) | 103 | + recs = append(recs, inNet...) |
| 108 | - recs = recs[:0] | 104 | + recs = append(recs, outNet...) |
| 109 | - recs = append(recs, inNet[:inTake]...) | | |
| 110 | - recs = append(recs, outNet[:outTake]...) | | |
| 111 | | 105 | |
| 112 | normalizePersonScores(recs) | 106 | normalizePersonScores(recs) |
| 113 | e.peopleCache.Add(userDID, recs) | 107 | e.peopleCache.Add(userDID, recs) |
| @@ -522,11 +516,17 @@ func (e *Engine) ComputeArticleRecommendationsOnDemand(ctx context.Context, user |
| 522 | return recs, rows.Err() | 516 | return recs, rows.Err() |
| 523 | } | 517 | } |
| 524 | | 518 | |
| 525 | -func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userDID string, limit int) ([]*PersonRecommendation, error) { | 519 | +func (e *Engine) computePeopleByFollowStatus(ctx context.Context, userDID string, followed bool, limit int) ([]*PersonRecommendation, error) { |
| | 520 | + var followCond string |
| | 521 | + if followed { |
| | 522 | + followCond = "f.target_did IS NOT NULL" |
| | 523 | + } else { |
| | 524 | + followCond = "f.target_did IS NULL" |
| | 525 | + } |
| | 526 | + |
| 526 | rows, err := e.db.QueryContext(ctx, ` | 527 | rows, err := e.db.QueryContext(ctx, ` |
| 527 | SELECT u.did, | 528 | SELECT u.did, |
| 528 | - sim.jaccard, sim.common_feeds, COALESCE(sim.common_likes, 0), COALESCE(sim.common_tags, 0), | 529 | + sim.jaccard, sim.common_feeds, COALESCE(sim.common_likes, 0), COALESCE(sim.common_tags, 0) |
| 529 | - CASE WHEN f.target_did IS NOT NULL THEN 1 ELSE 0 END | | |
| 530 | FROM ( | 530 | FROM ( |
| 531 | SELECT user_b AS peer_did, jaccard, common_feeds, common_likes, common_tags FROM recs.user_similarity WHERE user_a = ? | 531 | SELECT user_b AS peer_did, jaccard, common_feeds, common_likes, common_tags FROM recs.user_similarity WHERE user_a = ? |
| 532 | UNION ALL | 532 | UNION ALL |
| @@ -534,7 +534,8 @@ func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userD |
| 534 | ) sim | 534 | ) sim |
| 535 | JOIN main.users u ON u.did = sim.peer_did | 535 | JOIN main.users u ON u.did = sim.peer_did |
| 536 | LEFT JOIN main.follows f ON f.user_did = ? AND f.target_did = u.did | 536 | LEFT JOIN main.follows f ON f.user_did = ? AND f.target_did = u.did |
| 537 | - WHERE EXISTS (SELECT 1 FROM articles.subscriptions s JOIN articles.feeds f ON s.feed_url = f.feed_url WHERE s.user_did = u.did AND f.subscriber_count > 0) | 537 | + WHERE `+followCond+` |
| | 538 | + AND EXISTS (SELECT 1 FROM articles.subscriptions s JOIN articles.feeds f2 ON s.feed_url = f2.feed_url WHERE s.user_did = u.did AND f2.subscriber_count > 0) |
| 538 | AND NOT EXISTS (SELECT 1 FROM main.dismissed_recommendations d WHERE d.user_did = ? AND d.target_type = 'person' AND d.target_id = u.did) | 539 | AND NOT EXISTS (SELECT 1 FROM main.dismissed_recommendations d WHERE d.user_did = ? AND d.target_type = 'person' AND d.target_id = u.did) |
| 539 | ORDER BY sim.jaccard DESC | 540 | ORDER BY sim.jaccard DESC |
| 540 | LIMIT ? | 541 | LIMIT ? |
| @@ -547,13 +548,11 @@ func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userD |
| 547 | var results []*PersonRecommendation | 548 | var results []*PersonRecommendation |
| 548 | for rows.Next() { | 549 | for rows.Next() { |
| 549 | rec := &PersonRecommendation{} | 550 | rec := &PersonRecommendation{} |
| 550 | - var isFollowed int | | |
| 551 | if err := rows.Scan(&rec.DID, | 551 | if err := rows.Scan(&rec.DID, |
| 552 | - &rec.Jaccard, &rec.CommonFeeds, &rec.CommonLikes, &rec.CommonTags, | 552 | + &rec.Jaccard, &rec.CommonFeeds, &rec.CommonLikes, &rec.CommonTags); err != nil { |
| 553 | - &isFollowed); err != nil { | | |
| 554 | return nil, err | 553 | return nil, err |
| 555 | } | 554 | } |
| 556 | - rec.IsFollowed = isFollowed == 1 | 555 | + rec.IsFollowed = followed |
| 557 | results = append(results, rec) | 556 | results = append(results, rec) |
| 558 | } | 557 | } |
| 559 | return results, rows.Err() | 558 | return results, rows.Err() |