Skip to content

Instantly share code, notes, and snippets.

@bayleedev
Last active August 29, 2015 14:05
Show Gist options
  • Save bayleedev/be9cd721199825fa835b to your computer and use it in GitHub Desktop.
Save bayleedev/be9cd721199825fa835b to your computer and use it in GitHub Desktop.
require 'pry' # who doesn't want pry?
# Adds a `find` method to every model
module Finder
attr_accessor :types
def queries(*args)
@types = args
end
def find(request)
request = SolrRequest.new(request)
@types.each do |type|
klass = snake_to_const(type)
return klass.new.handle(request) if klass.handle?(request)
end
false
end
def snake_to_const(title)
Object.const_get(title.to_s.split('_').map { |e| e.capitalize }.join)
end
end
# Provider Model, has two solr query classes ProviderBySpecialty, ProviderByName
class Provider
extend Finder
queries :provider_by_specialty, :provider_by_name
end
# Location Model has one solr query class LocationByName
class Location
extend Finder
queries :location_by_name
end
# Creates the ProviderBySpecialty query
class ProviderBySpecialty
def self.handle?(request)
request.handle?({
need: [:specialist_id, :location],
want: [:distance, :standing_code, :facets, :fields, :limit]
})
end
def fields
(%w(score provider_id master_id geo specialist_id standing_code) +
%w(provider_practice_id disorder_id name_combo first_name middle_name) +
%w(last_name alias_first_name alias_middle_name alias_last_name) +
%w(alias_suffix display_name serial_SearchProviders)).join(',')
end
def facets(fields)
fields ||= [:us_educated, :is_abms_certified, :is_top_doctor, :is_patients_choice, :degree, :gender, :language_id]
fields.map do |field|
"facet.field={!key=#{field}}#{field}"
end
end
def handle(request)
[
'/providers_primary/select?wt=json',
"q=specialist_id:#{request.specialist_id} AND standing_code:#{request.standing_code || 'P'}",
"fl=#{request.fields || fields}",
"sort=sum(product(recip(geodist(geo,#{request.location}),0.2,1,1), 70), product(physician_algorithm_quality, 30)) desc",
'facet=true',
facets(request.facets),
'facet.range={!key=experience}experience',
'f.experience.facet.range.start=5',
'f.experience.facet.range.end=1000',
'f.experience.facet.range.gap=5',
'facet.range={!key=avg_wait_time}avg_wait_time',
'f.avg_wait_time.facet.range.start=0',
'f.avg_wait_time.facet.range.end=1000',
'f.avg_wait_time.facet.range.gap=10',
'facet.mincount=1',
"fq={!bbox pt=#{request.location} sfield=geo d=#{request.distance || '24.14016'}",
"rows=#{request.limit || 25}",
'defType=edismax'
].join('&')
end
end
# Creates the LocationByName query
class LocationByName
def self.handle?(request)
request.handle?(need: [:name], want: [:order, :fields])
end
def fields
%w(state city state_full geo:cc_geo zip aliases type population state_full geo geo_cc).join(',')
end
def handle(request)
[
'/places_primary/select?wt=json',
"q=((type:zip AND aliases_s_mv:(*\ #{request.name}* #{request.name}*)) OR city_s:(*\ #{request.name}* #{request.name}*))",
"fl=#{request.fields || fields}",
'fq={!tag=type}type:(city zip)',
"sort=#{request.order || 'population'} desc",
'group=true',
'group.field=city_state_s',
'group.sort=type asc,population desc',
'group.limit=1',
'group.ngroups=true',
'group.cache.percent=0',
'group.truncate=true',
'group.facet=false',
'rows=20',
'defType=edismax'
].join('&')
end
end
# Creates the ProviderByName query
class ProviderByName
def self.handle?(request)
request.handle?(need: [:name], want: [:fields, :facets])
end
def facets(fields)
fields ||= [:us_educated, :is_abms_certified, :is_top_doctor, :is_patients_choice, :degree, :gender, :language_id]
fields.map do |field|
"facet.field={!key=#{field}}#{field}"
end
end
def fields
(%w(score provider_id master_id geo specialist_id standing_code) +
%w(provider_practice_id disorder_id name_combo first_name middle_name) +
%w(last_name alias_first_name alias_middle_name alias_last_name) +
%w(alias_suffix display_name serial_SearchProviders)).join(',')
end
def handle(request)
[
'/providers_primary/select?wt=json',
"q=(display_name:#{request.name}*)",
"fl=#{request.fields || fields}",
'sort=geodist(geo,40.7142,-74.0064) asc, score desc',
'facet=true',
facets(request.facets),
'facet.range={!key=experience}experience',
'f.experience.facet.range.start=5',
'f.experience.facet.range.end=1000',
'f.experience.facet.range.gap=5',
'facet.range={!key=avg_wait_time}avg_wait_time',
'f.avg_wait_time.facet.range.start=0',
'f.avg_wait_time.facet.range.end=1000',
'f.avg_wait_time.facet.range.gap=10',
'facet.mincount=1',
'fq={!bbox pt=40.7142,-74.0064 sfield=geo d=10000}',
'rows=25',
'defType=edismax'
].join('&')
end
end
# Awesome param object that can help determine if you want him or not.
class SolrRequest
attr_accessor :params
def initialize(params = {})
@params = params
end
def handle_all_needs?(needs)
(needs & params.keys) == needs
end
def handle_only_wants?(wants)
(params.keys & wants) == params.keys
end
def handle?(qualifications)
handle_all_needs?(qualifications[:need]) and
handle_only_wants?(qualifications[:need] + qualifications[:want])
end
def method_missing(method, *args)
params[method]
end
end
# Example
puts Location.find(name: 'blaine')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment