Reputation: 357
I'm looking for some advice on the best way forward with my app which i have began to integrate elasticsearch for the first time. Im a bit of a beginner in rails but keen to dive in so forgive any glaring errors!
I followed a tutorial http://www.sitepoint.com/full-text-search-rails-elasticsearch/ and have also implemented some additional elasticsearch dsl features from reading documentation etc.. im just not convinced i'm there yet. (I certainly need to move out of the model, as currently most sits in the Product active record model.)
I am trying to implement a search on the Product model with ability to partial word search, fuzzy search (misspellings). From what I understand, I am able to set my own analyzers and filters for the elasticsearch, which I have done and currently reside in the Product model. I would like to move these to a more sensible location too, once I have established if indeed I am actually doing this correctly. I do get results when i search but im including things like deleting the index, creating a new index with mapping all in the end of the product model, if what i have below is not "the correct way", what better way is there than what i have to 1, implement elastic search using rails 2, seperate concerns more efficiently.
thanks and much appreciated
CODE:
lib/tasks/elasticsearch.rake:
require 'elasticsearch/rails/tasks/import'
View:
<%= form_tag search_index_path, class: 'search', method: :get do %>
<%= text_field_tag :query, params[:query], autocomplete: :off, placeholder: 'Search', class: 'search' %>
<% end %>
Gems i used:
gem 'elasticsearch-model', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
gem 'elasticsearch-rails', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
Search Controller:
class SearchController < ApplicationController
def index
if params[:query].nil?
@products = []
else
@products = Product.search(params[:query])
end
end
end
Product Model:
require 'elasticsearch/model'
class Product < ActiveRecord::Base
# ElasticSearch
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
settings index: {
number_of_shards: 1,
analysis: {
filter: {
trigrams_filter: {
type: 'ngram',
min_gram: 2,
max_gram: 10
},
content_filter: {
type: 'ngram',
min_gram: 4,
max_gram: 20
}
},
analyzer: {
index_trigrams_analyzer: {
type: 'custom',
tokenizer: 'standard',
filter: ['lowercase', 'trigrams_filter']
},
search_trigrams_analyzer: {
type: 'custom',
tokenizer: 'whitespace',
filter: ['lowercase']
},
english: {
tokenizer: 'standard',
filter: ['standard', 'lowercase', 'content_filter']
}
}
}
} do
mappings dynamic: 'false' do
indexes :name, index_analyzer: 'index_trigrams_analyzer', search_analyzer: 'search_trigrams_analyzer'
indexes :description, index_analyzer: 'english', search_analyzer: 'english'
indexes :manufacturer_name, index_analyzer: 'english', search_analyzer: 'english'
indexes :type_name, analyzer: 'snowball'
end
end
# Gem Plugins
acts_as_taggable
has_ancestry
has_paper_trail
@@ -99,6 +146,33 @@ def all_sizes
product_attributes.where(key: 'Size').map(&:value).join(',').split(',')
end
def self.search(query)
__elasticsearch__.search(
{
query: {
query_string: {
query: query,
fuzziness: 2,
default_operator: "AND",
fields: ['name^10', 'description', 'manufacturer_name', 'type_name']
}
},
highlight: {
pre_tags: ['<em>'],
post_tags: ['</em>'],
fields: {
name: {},
description: {}
}
}
}
)
end
def as_indexed_json(options={})
as_json(methods: [:manufacturer_name, :type_name])
end
end
# Delete the previous products index in Elasticsearch
Product.__elasticsearch__.client.indices.delete index: Product.index_name rescue nil
# Create the new index with the new mapping
Product.__elasticsearch__.client.indices.create \
index: Product.index_name,
body: { settings: Product.settings.to_hash, mappings: Product.mappings.to_hash }
# Index all article records from the DB to Elasticsearch
Product.import(force: true)
end
Upvotes: 0
Views: 2160
Reputation: 434
I can recommend searchkick:
https://github.com/ankane/searchkick
Several apps in production running with searchkick and it's easy to use.
Also check out the documentation of searchkick where a search for products is described in detail with facets, suggestions, etc.
Upvotes: 0
Reputation: 373
If you are using elasticsearch for searching,then i will recommend gem 'chewy' with elasticsearch server.
For more information just go to the links provided below.
for chewy:
https://github.com/toptal/chewy
Integrate chewy with elasticsearch:
http://www.toptal.com/ruby-on-rails/elasticsearch-for-ruby-on-rails-an-introduction-to-chewy
Thanks
Upvotes: 2