Revert friends-of-friends follow recommendation query to using a CTE (#29619)
This commit is contained in:
		
							parent
							
								
									b5115850bb
								
							
						
					
					
						commit
						d5063072c3
					
				@ -7,14 +7,35 @@ class AccountSuggestions::FriendsOfFriendsSource < AccountSuggestions::Source
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def source_query(account, limit: DEFAULT_LIMIT)
 | 
					  def source_query(account, limit: DEFAULT_LIMIT)
 | 
				
			||||||
    first_degree = account.following.where.not(hide_collections: true).select(:id).reorder(nil)
 | 
					    Account.find_by_sql([<<~SQL.squish, { id: account.id, limit: limit }]).map { |row| [row.id, row.frequency, row.followers_count] }
 | 
				
			||||||
    base_account_scope(account)
 | 
					      WITH first_degree AS (
 | 
				
			||||||
      .joins(:account_stat)
 | 
					          SELECT target_account_id
 | 
				
			||||||
      .joins(:passive_relationships).where(passive_relationships: { account_id: first_degree })
 | 
					          FROM follows
 | 
				
			||||||
      .group('accounts.id, account_stats.id')
 | 
					          JOIN accounts AS target_accounts ON follows.target_account_id = target_accounts.id
 | 
				
			||||||
      .reorder(frequency: :desc, followers_count: :desc)
 | 
					          WHERE account_id = :id
 | 
				
			||||||
      .limit(limit)
 | 
					            AND NOT target_accounts.hide_collections
 | 
				
			||||||
      .pluck(Arel.sql('accounts.id, COUNT(*) AS frequency, followers_count'))
 | 
					      )
 | 
				
			||||||
 | 
					      SELECT accounts.id, COUNT(*) AS frequency, account_stats.followers_count as followers_count
 | 
				
			||||||
 | 
					      FROM accounts
 | 
				
			||||||
 | 
					      JOIN follows ON follows.target_account_id = accounts.id
 | 
				
			||||||
 | 
					      JOIN account_stats ON account_stats.account_id = accounts.id
 | 
				
			||||||
 | 
					      LEFT OUTER JOIN follow_recommendation_mutes ON follow_recommendation_mutes.target_account_id = accounts.id AND follow_recommendation_mutes.account_id = :id
 | 
				
			||||||
 | 
					      WHERE follows.account_id IN (SELECT * FROM first_degree)
 | 
				
			||||||
 | 
					        AND NOT EXISTS (SELECT 1 FROM blocks b WHERE b.target_account_id = follows.target_account_id AND b.account_id = :id)
 | 
				
			||||||
 | 
					        AND NOT EXISTS (SELECT 1 FROM blocks b WHERE b.target_account_id = :id AND b.account_id = follows.target_account_id)
 | 
				
			||||||
 | 
					        AND NOT EXISTS (SELECT 1 FROM mutes m WHERE m.target_account_id = follows.target_account_id AND m.account_id = :id)
 | 
				
			||||||
 | 
					        AND (accounts.domain IS NULL OR NOT EXISTS (SELECT 1 FROM account_domain_blocks b WHERE b.account_id = :id AND b.domain = accounts.domain))
 | 
				
			||||||
 | 
					        AND NOT EXISTS (SELECT 1 FROM follows f WHERE f.target_account_id = follows.target_account_id AND f.account_id = :id)
 | 
				
			||||||
 | 
					        AND follows.target_account_id <> :id
 | 
				
			||||||
 | 
					        AND accounts.discoverable
 | 
				
			||||||
 | 
					        AND accounts.suspended_at IS NULL
 | 
				
			||||||
 | 
					        AND accounts.silenced_at IS NULL
 | 
				
			||||||
 | 
					        AND accounts.moved_to_account_id IS NULL
 | 
				
			||||||
 | 
					        AND follow_recommendation_mutes.target_account_id IS NULL
 | 
				
			||||||
 | 
					      GROUP BY accounts.id, account_stats.id
 | 
				
			||||||
 | 
					      ORDER BY frequency DESC, account_stats.followers_count ASC
 | 
				
			||||||
 | 
					      LIMIT :limit
 | 
				
			||||||
 | 
					    SQL
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
				
			|||||||
@ -76,19 +76,19 @@ RSpec.describe AccountSuggestions::FriendsOfFriendsSource do
 | 
				
			|||||||
      it 'contains correct underlying source data' do
 | 
					      it 'contains correct underlying source data' do
 | 
				
			||||||
        expect(source_query_values)
 | 
					        expect(source_query_values)
 | 
				
			||||||
          .to contain_exactly(
 | 
					          .to contain_exactly(
 | 
				
			||||||
            [eugen.id, 2, 3], # Followed by 2 friends of bob (eve, mallory), 3 followers total (breaks tie)
 | 
					            [john.id, 2, 2],  # Followed by 2 friends of bob (eve, mallory), 2 followers total (breaks tie)
 | 
				
			||||||
            [john.id, 2, 2],  # Followed by 2 friends of bob (eve, mallory), 2 followers total
 | 
					            [eugen.id, 2, 3], # Followed by 2 friends of bob (eve, mallory), 3 followers total
 | 
				
			||||||
            [neil.id, 1, 2],  # Followed by 1 friends of bob (mallory), 2 followers total (breaks tie)
 | 
					            [jerk.id, 1, 1],  # Followed by 1 friends of bob (eve), 1 followers total (breaks tie)
 | 
				
			||||||
            [jerk.id, 1, 1]   # Followed by 1 friends of bob (eve), 1 followers total
 | 
					            [neil.id, 1, 2]   # Followed by 1 friends of bob (mallory), 2 followers total
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      def expected_results
 | 
					      def expected_results
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
          [eugen.id, :friends_of_friends],
 | 
					 | 
				
			||||||
          [john.id, :friends_of_friends],
 | 
					          [john.id, :friends_of_friends],
 | 
				
			||||||
          [neil.id, :friends_of_friends],
 | 
					          [eugen.id, :friends_of_friends],
 | 
				
			||||||
          [jerk.id, :friends_of_friends],
 | 
					          [jerk.id, :friends_of_friends],
 | 
				
			||||||
 | 
					          [neil.id, :friends_of_friends],
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user