Skip to content

Instantly share code, notes, and snippets.

@phsacramento
Created January 21, 2017 01:00
Show Gist options
  • Save phsacramento/a03e79a151e04c1d6d48a27395fc2887 to your computer and use it in GitHub Desktop.
Save phsacramento/a03e79a151e04c1d6d48a27395fc2887 to your computer and use it in GitHub Desktop.
work in progress!
# encoding: UTF-8
module Searchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
settings index_configuration do
mapping dynamic: 'false' do
indexes :id, type: 'integer'
indexes :name, {
type: :multi_field,
fields: {
name: { type: 'string', analyzer: 'pedida_analyzer' },
name_gram: { type: 'string', index_analyzer: 'pedida_edge_ngram_analyzer' },
name_keyword: { type: 'string', index_analyzer: 'keyword' },
raw: { type: 'string', index: :not_analyzed }
}
}
indexes :location, type: 'geo_point'
indexes :district do
indexes :name, analyzer: 'pedida_analyzer'
indexes :slug, analyzer: 'keyword'
indexes :city_id, analyzer: 'pedida_analyzer'
end
indexes :bar_photos do
indexes :image_url, analyzer: 'pedida_analyzer'
end
indexes :city do
indexes :name, analyzer: 'pedida_analyzer'
indexes :slug, analyzer: 'keyword'
end
indexes :deals do
indexes :id, analyzer: 'pedida_analyzer'
indexes :name, analyzer: 'pedida_analyzer'
indexes :is_empty?, analyzer: 'pedida_analyzer'
indexes :is_expired?, analyzer: 'pedida_analyzer'
end
end
end
end
def as_indexed_json(options={})
as_json(
:suggest => {
:input => self.name,
:output => self.name,
:payload => {
:description => self.description
}
},
include: [
district: { only: [:name, :slug, :city_id] },
city: { only: [:name, :slug] },
bar_photos: {
only: [:image_url],
methods: [:image_url]
}
],
methods: [:deals, :location]
)
end
module ClassMethods
def sort_by_distance(lat,lng)
__elasticsearch__.search(
"*",
sort: {
_geo_distance: {
location: "#{lat},#{lon}",
order: "asc",
unit: "km"
}
},
size: 20
)
end
def find_by_city(city)
__elasticsearch__.search({ query: { match: { slug: city } } }).results.first
end
def search_with_term(query=nil, options={})
query = query.try(:upcase)
group_id = options[:group_id]
sort = options[:sort]
code_multiplier = 3
@search_definition = {
sort: {},
query: {},
filter: {},
highlight: {
order: 'score',
fields: {
name: {},
description: {},
applications: { number_of_fragments: 15 },
'district.name' => {}
}
}
}
if query.present?
@@query = query.gsub(/[\.\,\\\/\-*]/, "")
@@query2 = query.gsub(/[\(\)\[\]*]/, "")
@search_definition[:query] = {
dis_max: {
tie_breaker: 0.7,
boost: 1.8,
queries: [
{
multi_match: {
query: @@query2,
type: 'cross_fields',
fields: [
"name",
"name_gram",
"description_gram^0.5",
"description^2"
],
}
},
{
multi_match: {
query: @@query2,
type: 'most_fields',
fields: [
"name",
"description"
],
#fuzziness: "auto"
}
},
{
match: {
"label" => {
query: @@query,
boost: 0.1
},
}
},
{
match: {
"district.name" => {
query: @@query,
boost: 1.4
},
}
},
]
}
}
else
@search_definition[:sort] = { sort => 'asc' } if sort.present?
@search_definition[:query] = { match_all: {} }
end
if group_id.present?
@search_definition[:filter] = {
not: {
term: {
group_id: group_id
}
}
}
end
if options[:lat].present? && options[:lon].present?
options[:distance] ||= 100
@search_definition[:query][:bool][:must] << {
filtered: {
filter: {
geo_distance: {
distance: "#{options[:distance]}mi",
location: {
lat: options[:lat].to_f,
lon: options[:lon].to_f
}
}
}
}
}
end
__elasticsearch__.search(@search_definition)
end
protected
def index_configuration
@index_configuration ||= YAML.load_file(Rails.root.join('config', 'elasticsearch.yml'))
end
def configure_sort_field(field)
"#{field}"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment