Skip to content
Browse files

promote index level operations off of model and into ElasticSearchabl…

…e namespace
  • Loading branch information...
1 parent c81387b commit af9467a60e1621667a55f2200f4b43eb835f2e91 Ryan Sonnek committed Jan 23, 2012
View
2 .rvmrc
@@ -1 +1 @@
-rvm use ruby-1.9.2@elastic_searchable --create
+rvm use ruby-1.9.3@elastic_searchable --create
View
34 lib/elastic_searchable.rb
@@ -4,14 +4,13 @@
require 'elastic_searchable/active_record_extensions'
module ElasticSearchable
- DEFAULT_INDEX = 'elastic_searchable'
include HTTParty
format :json
base_uri 'localhost:9200'
class ElasticError < StandardError; end
class << self
- attr_accessor :logger, :default_index, :offline
+ attr_accessor :logger, :index_name, :index_settings, :offline
# execute a block of work without reindexing objects
def offline(&block)
@@ -34,7 +33,7 @@ def encode_json(options = {})
# ElasticSearchable.debug_output outputs all http traffic to console
def request(method, url, options = {})
options.merge! :headers => {'Content-Type' => 'application/json'}
- options.merge! :body => ElasticSearchable.encode_json(options.delete(:json_body)) if options[:json_body]
+ options.merge! :body => self.encode_json(options.delete(:json_body)) if options[:json_body]
response = self.send(method, url, options)
logger.debug "elasticsearch request: #{method} #{url} #{"took #{response['took']}ms" if response['took']}"
@@ -47,6 +46,33 @@ def escape_query(string)
string.to_s.gsub(/([\(\)\[\]\{\}\?\\\"!\^\+\-\*:~])/,'\\\\\1')
end
+ # create the index
+ # http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index.html
+ def create_index
+ options = {}
+ options[:settings] = self.index_settings if self.index_settings
+ self.request :put, self.request_path, :json_body => options
+ end
+
+ # explicitly refresh the index, making all operations performed since the last refresh
+ # available for search
+ #
+ # http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/refresh/
+ def refresh_index
+ self.request :post, self.request_path('_refresh')
+ end
+
+ # deletes the entire index
+ # http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/delete_index/
+ def delete_index
+ self.request :delete, self.request_path
+ end
+
+ # helper method to generate elasticsearch url for this index
+ def request_path(action = nil)
+ ['', index_name, action].compact.join('/')
+ end
+
private
# all elasticsearch rest calls return a json response when an error occurs. ex:
# {error: 'an error occurred' }
@@ -63,5 +89,5 @@ def validate_response(response)
# configure default index to be elastic_searchable
# one index can hold many object 'types'
-ElasticSearchable.default_index = ElasticSearchable::DEFAULT_INDEX
+ElasticSearchable.index_name = 'elastic_searchable'
View
9 lib/elastic_searchable/active_record_extensions.rb
@@ -8,9 +8,7 @@
module ElasticSearchable
module ActiveRecordExtensions
# Valid options:
- # :index (optional) configure index to store data in. default to ElasticSearchable.default_index
# :type (optional) configue type to store data in. default to model table name
- # :index_options (optional) configure index properties (ex: tokenizer)
# :mapping (optional) configure field properties for this model (ex: skip analyzer for field)
# :if (optional) reference symbol/proc condition to only index when condition is true
# :unless (optional) reference symbol/proc condition to skip indexing when condition is true
@@ -29,6 +27,13 @@ def elastic_searchable(options = {})
cattr_accessor :elastic_options
self.elastic_options = options.symbolize_keys.merge(:unless => Array.wrap(options[:unless]).push(:elasticsearch_offline?))
+ if self.elastic_options[:index_options]
+ ActiveSupport::Deprecation.warn ":index_options has been deprecated. Use ElasticSearchable.index_settings instead.", caller
+ end
+ if self.elastic_options[:index]
+ ActiveSupport::Deprecation.warn ":index has been deprecated. Use ElasticSearchable.index_name instead.", caller
+ end
+
extend ElasticSearchable::Indexing::ClassMethods
extend ElasticSearchable::Queries
View
35 lib/elastic_searchable/index.rb
@@ -15,29 +15,6 @@ def update_index_mapping
end
end
- # create the index
- # http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index.html
- def create_index
- options = {}
- options.merge! :settings => self.elastic_options[:index_options] if self.elastic_options[:index_options]
- options.merge! :mappings => {index_type => self.elastic_options[:mapping]} if self.elastic_options[:mapping]
- ElasticSearchable.request :put, index_path, :json_body => options
- end
-
- # explicitly refresh the index, making all operations performed since the last refresh
- # available for search
- #
- # http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/refresh/
- def refresh_index
- ElasticSearchable.request :post, index_path('_refresh')
- end
-
- # deletes the entire index
- # http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/delete_index/
- def delete_index
- ElasticSearchable.request :delete, index_path
- end
-
# delete one record from the index
# http://www.elasticsearch.com/docs/elasticsearch/rest_api/delete/
def delete_id_from_index(id)
@@ -48,12 +25,7 @@ def delete_id_from_index(id)
# helper method to generate elasticsearch url for this object type
def index_type_path(action = nil)
- index_path [index_type, action].compact.join('/')
- end
-
- # helper method to generate elasticsearch url for this index
- def index_path(action = nil)
- ['', index_name, action].compact.join('/')
+ ElasticSearchable.request_path [index_type, action].compact.join('/')
end
# reindex all records using bulk api
@@ -78,7 +50,7 @@ def reindex(options = {})
next unless record.should_index?
begin
doc = ElasticSearchable.encode_json(record.as_json_for_index)
- actions << ElasticSearchable.encode_json({:index => {'_index' => index_name, '_type' => index_type, '_id' => record.id}})
+ actions << ElasticSearchable.encode_json({:index => {'_index' => ElasticSearchable.index_name, '_type' => index_type, '_id' => record.id}})
actions << doc
rescue => e
ElasticSearchable.logger.warn "Unable to bulk index record: #{record.inspect} [#{e.message}]"
@@ -97,9 +69,6 @@ def reindex(options = {})
end
private
- def index_name
- self.elastic_options[:index] || ElasticSearchable.default_index
- end
def index_type
self.elastic_options[:type] || self.table_name
end
View
2 test/helper.rb
@@ -19,6 +19,6 @@
class Test::Unit::TestCase
def delete_index
- ElasticSearchable.delete '/elastic_searchable' rescue nil
+ ElasticSearchable.delete_index rescue nil
end
end
View
86 test/test_elastic_searchable.rb
@@ -3,9 +3,9 @@
class TestElasticSearchable < Test::Unit::TestCase
def setup
delete_index
+ ElasticSearchable.index_settings = {'number_of_replicas' => 0, 'number_of_shards' => 1}
+ # ElasticSearchable.debug_output
end
- # ElasticSearchable.debug_output
- SINGLE_NODE_CLUSTER_CONFIG = {'number_of_replicas' => 0, 'number_of_shards' => 1}
context 'non elastic activerecord class' do
class Parent < ActiveRecord::Base
@@ -29,7 +29,7 @@ class Parent < ActiveRecord::Base
end
class Post < ActiveRecord::Base
- elastic_searchable :index_options => SINGLE_NODE_CLUSTER_CONFIG
+ elastic_searchable
after_index :indexed
after_index :indexed_on_create, :on => :create
after_index :indexed_on_update, :on => :update
@@ -76,10 +76,10 @@ def indexed_on_update?
end
end
- context 'Model.create_index' do
+ context 'ElasticSearchable.create_index' do
setup do
- Post.create_index
- Post.refresh_index
+ ElasticSearchable.create_index
+ ElasticSearchable.refresh_index
@status = ElasticSearchable.request :get, '/elastic_searchable/_status'
end
should 'have created index' do
@@ -140,11 +140,11 @@ def indexed_on_update?
context 'with empty index when multiple database records' do
setup do
Post.delete_all
- Post.create_index
+ ElasticSearchable.create_index
@first_post = Post.create :title => 'foo', :body => "first bar"
@second_post = Post.create :title => 'foo', :body => "second bar"
- Post.delete_index
- Post.create_index
+ ElasticSearchable.delete_index
+ ElasticSearchable.create_index
end
should 'not raise error if error occurs reindexing model' do
ElasticSearchable.expects(:request).raises(ElasticSearchable::ElasticError.new('faux error'))
@@ -161,7 +161,7 @@ def indexed_on_update?
context 'Model.reindex' do
setup do
Post.reindex :per_page => 1, :scope => Post.scoped(:order => 'body desc')
- Post.refresh_index
+ ElasticSearchable.refresh_index
end
should 'have reindexed both records' do
assert_nothing_raised do
@@ -174,10 +174,10 @@ def indexed_on_update?
context 'with index containing multiple results' do
setup do
- Post.create_index
+ ElasticSearchable.create_index
@first_post = Post.create :title => 'foo', :body => "first bar"
@second_post = Post.create :title => 'foo', :body => "second bar"
- Post.refresh_index
+ ElasticSearchable.refresh_index
end
context 'searching for results' do
@@ -267,7 +267,7 @@ def indexed_on_update?
context 'destroying one object' do
setup do
@first_post.destroy
- Post.refresh_index
+ ElasticSearchable.refresh_index
end
should 'be removed from the index' do
@request = ElasticSearchable.get "/elastic_searchable/posts/#{@first_post.id}"
@@ -278,7 +278,7 @@ def indexed_on_update?
class Blog < ActiveRecord::Base
- elastic_searchable :if => proc {|b| b.should_index? }, :index_options => SINGLE_NODE_CLUSTER_CONFIG
+ elastic_searchable :if => proc {|b| b.should_index? }
def should_index?
false
end
@@ -297,54 +297,19 @@ def should_index?
end
end
- class User < ActiveRecord::Base
- elastic_searchable :index_options => {
- 'number_of_replicas' => 0,
- 'number_of_shards' => 1,
- "analysis.analyzer.default.tokenizer" => 'standard',
- "analysis.analyzer.default.filter" => ["standard", "lowercase", 'porterStem']},
- :mapping => {:properties => {:name => {:type => 'string', :index => 'not_analyzed'}}}
- end
- context 'activerecord class with :index_options and :mapping' do
- context 'creating index' do
- setup do
- User.create_index
- end
- should 'have used custom index_options' do
- @status = ElasticSearchable.request :get, '/elastic_searchable/_settings'
- expected = {
- "index.number_of_replicas" => "0",
- "index.number_of_shards" => "1",
- "index.analysis.analyzer.default.tokenizer" => "standard",
- "index.analysis.analyzer.default.filter.0" => "standard",
- "index.analysis.analyzer.default.filter.1" => "lowercase",
- "index.analysis.analyzer.default.filter.2" => "porterStem"
- }
- assert_equal expected, @status['elastic_searchable']['settings'], @status.inspect
- end
- should 'have set mapping' do
- @status = ElasticSearchable.request :get, '/elastic_searchable/users/_mapping'
- expected = {
- "name"=> {"type"=>"string", "index"=>"not_analyzed"}
- }
- assert_equal expected, @status['users']['properties'], @status.inspect
- end
- end
- end
-
class Friend < ActiveRecord::Base
belongs_to :book
- elastic_searchable :json => {:include => {:book => {:only => :title}}, :only => :name}, :index_options => SINGLE_NODE_CLUSTER_CONFIG
+ elastic_searchable :json => {:include => {:book => {:only => :title}}, :only => :name}
end
context 'activerecord class with optional :json config' do
context 'creating index' do
setup do
- Friend.create_index
+ ElasticSearchable.create_index
@book = Book.create! :isbn => '123abc', :title => 'another world'
@friend = Friend.new :name => 'bob', :favorite_color => 'red'
@friend.book = @book
@friend.save!
- Friend.refresh_index
+ ElasticSearchable.refresh_index
end
should 'index json with configuration' do
@response = ElasticSearchable.request :get, "/elastic_searchable/friends/#{@friend.id}"
@@ -360,15 +325,16 @@ class Friend < ActiveRecord::Base
end
end
- context 'updating ElasticSearchable.default_index' do
+ context '.index_name' do
setup do
- ElasticSearchable.default_index = 'my_new_index'
+ @orig_index_name = ElasticSearchable.index_name
+ ElasticSearchable.index_name = 'my_new_index'
end
teardown do
- ElasticSearchable.default_index = ElasticSearchable::DEFAULT_INDEX
+ ElasticSearchable.index_name = @orig_index_name
end
should 'change default index' do
- assert_equal 'my_new_index', ElasticSearchable.default_index
+ assert_equal 'my_new_index', ElasticSearchable.index_name
end
end
@@ -385,7 +351,7 @@ def percolated
context 'Book class with after_percolate callback' do
context 'with created index' do
setup do
- Book.create_index
+ ElasticSearchable.create_index
end
context "when index has configured percolation" do
setup do
@@ -443,17 +409,17 @@ def percolated
end
class MaxPageSizeClass < ActiveRecord::Base
- elastic_searchable :index_options => SINGLE_NODE_CLUSTER_CONFIG
+ elastic_searchable
def self.max_per_page
1
end
end
context 'with 2 MaxPageSizeClass instances' do
setup do
- MaxPageSizeClass.create_index
+ ElasticSearchable.create_index
@first = MaxPageSizeClass.create! :name => 'foo one'
@second = MaxPageSizeClass.create! :name => 'foo two'
- MaxPageSizeClass.refresh_index
+ ElasticSearchable.refresh_index
end
context 'MaxPageSizeClass.search with default options and WillPaginate' do
setup do

0 comments on commit af9467a

Please sign in to comment.
Something went wrong with that request. Please try again.