Created
February 16, 2017 01:37
-
-
Save phsacramento/9227f91cf005cd7829b609032eda132e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: UTF-8 | |
module Searchable | |
extend ActiveSupport::Concern | |
included do | |
include Elasticsearch::Model | |
settings index_configuration do | |
mapping do | |
indexes :unit, { | |
type: :multi_field, | |
fields: { | |
unit: { type: 'string', analyzer: 'bmx_analyzer' }, | |
unit_keyword: { type: 'string', analyzer: 'keyword' } | |
} | |
} | |
indexes :code, { | |
type: :multi_field, | |
fields: { | |
code: { type: 'string', analyzer: 'bmx_analyzer' }, | |
code_gram: { type: 'string', index_analyzer: 'bmx_ngram_analyzer' }, | |
code_keyword: { type: 'string', analyzer: 'keyword' }, | |
code_delimiter: { type: 'string', analyzer: 'bmx_word_analyzer' } | |
} | |
} | |
indexes :slug, analyzer: 'keyword' | |
indexes :description, { | |
type: :multi_field, | |
fields: { | |
description: { type: 'string', analyzer: 'bmx_analyzer' }, | |
description_gram: { type: 'string', index_analyzer: 'bmx_edge_ngram_analyzer' }, | |
description_keyword: { type: 'string', index_analyzer: 'keyword' } | |
} | |
} | |
indexes :observation, analyzer: 'bmx_analyzer' | |
indexes :original_code, analyzer: 'bmx_analyzer' | |
indexes :secundary_code, analyzer: 'bmx_analyzer' | |
indexes :group_id, index: 'not_analyzed' | |
indexes :producer do | |
indexes :name, analyzer: 'bmx_analyzer' | |
indexes :slug, analyzer: 'keyword' | |
end | |
indexes :part_distributors do | |
indexes :city, analyzer: 'bmx_analyzer' | |
indexes :state, analyzer: 'bmx_analyzer' | |
indexes :price, analyzer: 'bmx_analyzer' | |
indexes :external_url, analyzer: 'bmx_analyzer' | |
indexes :name, index: 'not_analyzed', include_in_all: false | |
indexes :quantity, index: 'not_analyzed', include_in_all: false | |
indexes :email, index: 'not_analyzed', include_in_all: false | |
indexes :site, index: 'not_analyzed', include_in_all: false | |
indexes :phone, index: 'not_analyzed', include_in_all: false | |
indexes :address, index: 'not_analyzed', include_in_all: false | |
indexes :neighbourhood, index: 'not_analyzed', include_in_all: false | |
indexes :address_number, index: 'not_analyzed', include_in_all: false | |
indexes :address_complement, index: 'not_analyzed', include_in_all: false | |
indexes :zip_code, index: 'not_analyzed', include_in_all: false | |
end | |
indexes :related_parts_as_indexed_json do | |
indexes :code, index: 'not_analyzed', include_in_all: false | |
indexes :producer_name, index: 'not_analyzed', include_in_all: false | |
indexes :part_distributors_as_indexed_json do | |
indexes :name, index: 'not_analyzed', include_in_all: false | |
indexes :quantity, index: 'not_analyzed', include_in_all: false | |
indexes :price, index: 'not_analyzed', include_in_all: false | |
indexes :email, index: 'not_analyzed', include_in_all: false | |
indexes :site, index: 'not_analyzed', include_in_all: false | |
indexes :phone, index: 'not_analyzed', include_in_all: false | |
indexes :address, index: 'not_analyzed', include_in_all: false | |
indexes :neighbourhood, index: 'not_analyzed', include_in_all: false | |
indexes :address_number, index: 'not_analyzed', include_in_all: false | |
indexes :address_complement, index: 'not_analyzed', include_in_all: false | |
indexes :city, index: 'not_analyzed', include_in_all: false | |
indexes :state, index: 'not_analyzed', include_in_all: false | |
indexes :zip_code, index: 'not_analyzed', include_in_all: false | |
indexes :external_url, analyzer: 'bmx_analyzer' | |
end | |
end | |
indexes :applications, analyzer: 'bmx_analyzer' | |
end | |
end | |
index_name ENV['INDEX'] || "parts_#{Rails.env}" | |
document_type "part" | |
end | |
def as_indexed_json(options={}) | |
as_json( | |
except: [ | |
:id, :_id, :producer_id, :distributor_ids, | |
:created_at, :updated_at | |
], | |
include: { | |
producer: { only: [:name, :slug] }, | |
part_distributors: { | |
only: [:name, :neighbourhood, :address, :address_number, :address_complement, :city, :phone, :email, :state, :zip_code, :price, :quantity, :site, :external_url], | |
methods: [:name, :neighbourhood, :address, :address_number, :address_complement, :city, :phone, :email, :state, :zip_code, :price, :quantity, :site, :external_url] | |
} | |
}, | |
methods: [:related_parts_as_indexed_json, :applications, :group_id] | |
) | |
end | |
protected | |
def index_document | |
__elasticsearch__.index_document | |
end | |
def delete_document | |
__elasticsearch__.delete_document | |
end | |
module ClassMethods | |
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: { | |
code: {}, | |
description: {}, | |
applications: { number_of_fragments: 15 }, | |
'producer.name' => {} | |
} | |
} | |
} | |
if query.present? | |
@@query = query.gsub(/[\.\,\\\/\-*]/, "") | |
@@query2 = query.gsub(/[\(\)\[\]*]/, "") | |
@search_definition[:query] = { | |
dis_max: { | |
tie_breaker: 0.7, | |
boost: 1.2, | |
queries: [ | |
{ | |
multi_match: { | |
query: @@query, | |
type: 'cross_fields', | |
fields: [ | |
"code", | |
"code_gram", | |
], | |
} | |
}, | |
{ | |
multi_match: { | |
query: @@query2, | |
type: 'cross_fields', | |
fields: [ | |
"code", | |
"code_gram", | |
"description_gram^0.5", | |
"description^2", | |
"applications", | |
], | |
} | |
}, | |
{ | |
multi_match: { | |
query: @@query2, | |
type: 'most_fields', | |
fields: [ | |
"code", | |
"description", | |
"applications", | |
], | |
#fuzziness: "auto" | |
} | |
}, | |
{ | |
match: { | |
"observation" => { | |
query: @@query, | |
boost: 0.1 | |
}, | |
} | |
}, | |
{ | |
match: { | |
"producer.name" => { | |
query: @@query, | |
boost: 1.4 | |
}, | |
} | |
}, | |
] | |
} | |
} | |
#else | |
# @search_definition[:query] = { match_all: {} } | |
end | |
if group_id.present? | |
@search_definition[:filter] = { | |
not: { | |
term: { | |
group_id: group_id | |
} | |
} | |
} | |
end | |
if sort.present? | |
@search_definition[:sort] = [ | |
{ | |
configure_sort_field(sort) => { | |
order: 'asc' | |
} | |
} | |
] | |
end | |
__elasticsearch__.search(@search_definition) | |
end | |
def find_by_code(code_slug) | |
__elasticsearch__.search({ query: { match: { slug: code_slug } } }).results.first | |
end | |
def find_by_producer_and_code(producer_slug, code_slug) | |
__elasticsearch__.search({ filter: { and: [ { term: { slug: code_slug } }, | |
{ term: { 'producer.slug' => producer_slug } } ] } }).results.first | |
end | |
protected | |
def index_configuration | |
@index_configuration ||= YAML.load_file(Rails.root.join('config', 'elasticsearch.yml')) | |
end | |
def configure_sort_field(field) | |
field.inquiry.producer? ? "#{field}.slug" : "#{field}_keyword" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment