sylvainkalache / linkedin-search

1st degree connections search

Home Page:http://linkedinsearch.algolia.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LinkedIn Search

This is the Rails 4 application providing LinkedIn Search. It's based on algoliasearch-client-ruby and omniauth-linkedin.

Index settings

Algolia.init application_id: ENV['ALGOLIA_APPLICATION_ID'], api_key: ENV['ALGOLIA_API_KEY']
INDEX = Algolia::Index.new("linkedin_#{Rails.env}")
INDEX.set_settings({
  attributesToIndex: ['last_name', 'first_name', 'unordered(headline)', 'unordered(industry)', 'unordered(location)', 'unordered(positions.company.name)'],
  customRanking: ['desc(num_connections)', 'asc(last_name)'],
  attributesForFaceting: ['industry', 'location', 'positions.company.name']
})

Record definition

FIELDS = ["id", "first-name", "last-name", "headline", "industry", "picture-url",
 "public-profile-url", "location", "num-connections", "positions"]
LIMIT = 100

def crawl_connections!(token, secret)
  client = LinkedIn::Client.new(ENV['OMNIAUTH_PROVIDER_KEY'], ENV['OMNIAUTH_PROVIDER_SECRET'])
  client.authorize_from_access(token, secret)
  INDEX.add_object build_algolia_object(client.profile(fields: FIELDS))
  start = 0
  connections = []
  loop do
    slice = client.connections(fields: FIELDS, start: start, count: LIMIT).all
    break if slice.nil? || slice.empty?
    connections += slice.map { |c| build_algolia_object(c) }
    start += LIMIT
  end
  searchable_connections = connections.compact
  update_attribute :non_searchable_counter, (connections.length - searchable_connections.length)
  INDEX.add_objects(searchable_connections)
end

private
def build_algolia_object(c)
  return nil if c.id.blank? || c.id == 'private' # some connections are hidden (strict privacy settings)
  {
    objectID: "#{uid}_#{c.id}",
    first_name: c.first_name,
    last_name: c.last_name,
    headline: c.headline,
    industry: c.industry,
    location: c.location.try(:name),
    picture_url: c.picture_url,
    url: c.public_profile_url,
    num_connections: c.num_connections,
    positions: (c.positions.try(:all) || []).map { |p|
      {
        company: p.company.to_h,
        is_current: p.is_current,
        start_date: p.start_date.to_h,
        summary: p.summary,
        title: p.title
      }
    },
    _tags: [ uid ] # used for security
  }
end

Secure indexing

Each record (connection) is tagged with its owner id (Your LinkedIn UID) and we use a per-user generated secured API key to call Algolia's REST API.

@secured_api_key = Algolia.generate_secured_api_key(ENV['ALGOLIA_API_KEY_SEARCH_ONLY'], current_user.uid)
var algolia = new AlgoliaSearch('#{ENV['ALGOLIA_APPLICATION_ID']}', '#{@secured_api_key}');
algolia.setSecurityTags('#{current_user.uid}');

About

1st degree connections search

http://linkedinsearch.algolia.com


Languages

Language:Ruby 85.6%Language:CSS 12.6%Language:JavaScript 1.9%