简体   繁体   中英

Rails 4, elasticsearch-rails

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

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM