elastics 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +19 -0
- data/README.md +103 -0
- data/Rakefile +11 -0
- data/elastics.gemspec +25 -0
- data/lib/elastics/active_record/helper_methods.rb +59 -0
- data/lib/elastics/active_record/instrumentation.rb +15 -0
- data/lib/elastics/active_record/log_subscriber.rb +27 -0
- data/lib/elastics/active_record/model_schema.rb +39 -0
- data/lib/elastics/active_record.rb +36 -0
- data/lib/elastics/client.rb +97 -0
- data/lib/elastics/query_helper.rb +27 -0
- data/lib/elastics/railtie.rb +18 -0
- data/lib/elastics/tasks/indices.rb +42 -0
- data/lib/elastics/tasks/mappings.rb +40 -0
- data/lib/elastics/tasks.rb +35 -0
- data/lib/elastics/version.rb +7 -0
- data/lib/elastics.rb +13 -0
- data/lib/tasks/elastics.rake +20 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 31208a61d960f7b411e4b6588d8c7aa2f8741e59
|
4
|
+
data.tar.gz: 64d46d44db05a22ac1d84a5155cb5ea6489327aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 998636cd31b1a9229d381544206fb3a17e4c7bef3ba6d4b26935e7d7254e55ab545a8247668063a61b64979115d3332cb1bd7f83fa1c95d3123ec1ab10b3b987
|
7
|
+
data.tar.gz: 7be4cb9870cd5cc3e053f492fd55479e1ab41287790047987b9897430d8dddab3ba2b8e3689038cd04e8361a00383d082fd2b66b1625cce82a734b584abf0ec1
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
elastics (0.1.0)
|
5
|
+
httpclient (~> 2.4.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
httpclient (2.4.0)
|
11
|
+
rake (10.3.2)
|
12
|
+
|
13
|
+
PLATFORMS
|
14
|
+
ruby
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
bundler (~> 1.5)
|
18
|
+
elastics!
|
19
|
+
rake (~> 10)
|
data/README.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# elastics
|
2
|
+
|
3
|
+
Simple ElasticSearch client.
|
4
|
+
|
5
|
+
Fast and thread-safe [httpclient](https://github.com/nahi/httpclient) under the hood.
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# Gemfile
|
11
|
+
gem 'elastics', github: 'printercu/elastics-rb'
|
12
|
+
```
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
### Plain
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# initialize client with
|
20
|
+
client = Elastics::Client.new(options)
|
21
|
+
# options is hash with
|
22
|
+
# :host
|
23
|
+
# :port
|
24
|
+
# :index - (default index)
|
25
|
+
# :type - (default type)
|
26
|
+
|
27
|
+
# basic request
|
28
|
+
client.request(options)
|
29
|
+
# options is hash with
|
30
|
+
# :method - default :get
|
31
|
+
# :data - post body
|
32
|
+
# :query - query string params
|
33
|
+
# :index, :type, :id - query path params to override defaults
|
34
|
+
|
35
|
+
# method shortcuts for #put, #post #delete
|
36
|
+
client.delete(params)
|
37
|
+
|
38
|
+
# getter/setter shortcuts
|
39
|
+
client.set(id, data)
|
40
|
+
client.get(id)
|
41
|
+
client.get(params) # as usual
|
42
|
+
|
43
|
+
# other shortcuts (set method & id)
|
44
|
+
client.put_mapping(index: index, type: type, data: mapping)
|
45
|
+
client.search(params)
|
46
|
+
client.index(params) # PUT if :id is set, otherwise POST
|
47
|
+
|
48
|
+
# utils
|
49
|
+
client.index_exists?(name)
|
50
|
+
```
|
51
|
+
|
52
|
+
### ActiveRecord
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class User < ActiveRecord::Base
|
56
|
+
indexed_with_elastics
|
57
|
+
# optionally pass :index, :type
|
58
|
+
|
59
|
+
# optionally override to export only selected fields
|
60
|
+
def to_elastics
|
61
|
+
serializable_hash(only: [:id, :first_name, :last_name])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
User.search_elastics(data)
|
66
|
+
```
|
67
|
+
|
68
|
+
#### Configure
|
69
|
+
```yml
|
70
|
+
# database.yml
|
71
|
+
development:
|
72
|
+
elastics:
|
73
|
+
# use single index (app_dev/users, app_dev/documents)
|
74
|
+
index: app_dev
|
75
|
+
|
76
|
+
# use index per type (app_dev_users/users, app_dev_documents/documents)
|
77
|
+
index_prefix: app_dev_
|
78
|
+
|
79
|
+
production:
|
80
|
+
elastics:
|
81
|
+
host: 10.0.0.1
|
82
|
+
port: 1234
|
83
|
+
|
84
|
+
index: app
|
85
|
+
# or
|
86
|
+
index_prefix: app_
|
87
|
+
```
|
88
|
+
|
89
|
+
#### Mappings & index settings
|
90
|
+
Mappings & index settings `.yml` files are placed in
|
91
|
+
`db/elastics/mappings` & `db/elastics/indices`.
|
92
|
+
For now this files are not related to models and only used by rake tasks.
|
93
|
+
|
94
|
+
- `rake elastics:create` (or `Elastics::Tasks.create_indices`)
|
95
|
+
creates index with settings for each file from `indices` folder.
|
96
|
+
For single index it only processes file with index name.
|
97
|
+
For multiple indices each index name is `#{index_prefix}#{file.basename}`
|
98
|
+
|
99
|
+
- `rake elastics:migrate` (or `Elastics::Tasks.migrate`)
|
100
|
+
puts mappings from `mappings` folder.
|
101
|
+
|
102
|
+
## License
|
103
|
+
MIT
|
data/Rakefile
ADDED
data/elastics.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'elastics/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'elastics'
|
8
|
+
spec.version = Elastics::VERSION
|
9
|
+
spec.authors = ['Max Melentiev']
|
10
|
+
spec.email = ['melentievm@gmail.com']
|
11
|
+
spec.summary = 'ElasticSearch client with ActiveRecord integration'
|
12
|
+
spec.description = 'Lightweight and extensible elasticsearch client'
|
13
|
+
spec.homepage = 'http://github.com/printercu/elastics-rb'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'httpclient', '~> 2.4.0'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10'
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Elastics
|
2
|
+
module ActiveRecord
|
3
|
+
module HelperMethods
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def search(data = {}, routing = nil)
|
8
|
+
es_results = search_elastics(data, routing)
|
9
|
+
ids = es_results['hits'.freeze]['hits'.freeze].map { |x| x['_id'.freeze].to_i }
|
10
|
+
relation = where(id: ids)
|
11
|
+
items_by_id = relation.index_by(&:id)
|
12
|
+
collection = ids.map { |i| items_by_id[i] }
|
13
|
+
{
|
14
|
+
collection: collection,
|
15
|
+
relation: relation,
|
16
|
+
search: es_results,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def search_elastics(data = {}, routing = nil)
|
21
|
+
request = {
|
22
|
+
id: :_search,
|
23
|
+
data: data,
|
24
|
+
}
|
25
|
+
request[:query] = {routing: routing} if routing
|
26
|
+
request_elastics(request)
|
27
|
+
end
|
28
|
+
|
29
|
+
def request_elastics(params)
|
30
|
+
request = {
|
31
|
+
index: elastics_index_name,
|
32
|
+
type: elastics_type_name,
|
33
|
+
}.merge!(params)
|
34
|
+
elastics.request(request)
|
35
|
+
end
|
36
|
+
|
37
|
+
def elastics_mapping
|
38
|
+
request_elastics(method: :get, id: :_mapping)
|
39
|
+
end
|
40
|
+
|
41
|
+
def reindex(*args)
|
42
|
+
find_each(*args, &:index_elastics)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def index_elastics
|
47
|
+
self.class.request_elastics(method: :post, id: id, data: to_elastics)
|
48
|
+
end
|
49
|
+
|
50
|
+
def delete_elastics
|
51
|
+
self.class.request_elastics(method: :delete, id: id)
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_elastics
|
55
|
+
as_json
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Elastics
|
2
|
+
module ActiveRecord
|
3
|
+
module Instrumentation
|
4
|
+
def request_elastics(params = {})
|
5
|
+
data = {
|
6
|
+
name: name,
|
7
|
+
request: params,
|
8
|
+
}
|
9
|
+
ActiveSupport::Notifications.instrument 'request_elastics.active_record', data do
|
10
|
+
super(params)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Elastics
|
2
|
+
module ActiveRecord
|
3
|
+
module LogSubscriber
|
4
|
+
def self.included(base)
|
5
|
+
instance_methods.each { |method| base.method_added(method) }
|
6
|
+
end
|
7
|
+
|
8
|
+
def request_elastics(event)
|
9
|
+
return unless logger.debug?
|
10
|
+
|
11
|
+
payload = event.payload
|
12
|
+
|
13
|
+
name = "#{payload[:name]} elastics (#{event.duration.round(1)}ms)"
|
14
|
+
request = payload[:request].to_json
|
15
|
+
|
16
|
+
if odd?
|
17
|
+
name = color(name, ActiveSupport::LogSubscriber::CYAN, true)
|
18
|
+
request = color(request, nil, true)
|
19
|
+
else
|
20
|
+
name = color(name, ActiveSupport::LogSubscriber::MAGENTA, true)
|
21
|
+
end
|
22
|
+
|
23
|
+
debug " #{name} #{request}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Elastics
|
2
|
+
module ActiveRecord
|
3
|
+
module ModelSchema
|
4
|
+
attr_writer :elastics_index_name, :elastics_type_name
|
5
|
+
|
6
|
+
def elastics_index_name
|
7
|
+
reset_elastics_index_name unless defined?(@elastics_index_name)
|
8
|
+
@elastics_index_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def elastics_type_name
|
12
|
+
reset_elastics_index_name unless defined?(@elastics_type_name)
|
13
|
+
@elastics_type_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset_elastics_index_name
|
17
|
+
superclass_responds = superclass.respond_to?(:elastics_index_name)
|
18
|
+
index = if abstract_class? && superclass_responds
|
19
|
+
superclass == ::ActiveRecord::Base ? nil : superclass.elastics_index_name
|
20
|
+
elsif superclass.abstract_class? && superclass_responds
|
21
|
+
superclass.elastics_index_name || compute_elastics_index_name
|
22
|
+
else
|
23
|
+
compute_elastics_index_name
|
24
|
+
end
|
25
|
+
@elastics_index_name = index
|
26
|
+
@elastics_type_name = compute_elastics_type_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def compute_elastics_index_name(name = nil)
|
30
|
+
elastics_config[:index] ||
|
31
|
+
"#{elastics_config[:index_prefix]}#{name || table_name.singularize}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def compute_elastics_type_name
|
35
|
+
model_name.to_s.demodulize.underscore.singularize
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Elastics
|
2
|
+
module ActiveRecord
|
3
|
+
extend ActiveSupport::Autoload
|
4
|
+
|
5
|
+
autoload :ModelSchema
|
6
|
+
autoload :HelperMethods
|
7
|
+
autoload :Instrumentation
|
8
|
+
autoload :LogSubscriber
|
9
|
+
|
10
|
+
def elastics_config
|
11
|
+
@elastics_config ||= connection_config[:elastics].try!(:with_indifferent_access) ||
|
12
|
+
raise('No elastics configuration in database.yml')
|
13
|
+
end
|
14
|
+
|
15
|
+
def elastics
|
16
|
+
@elastics ||= Client.new elastics_config.slice(:host, :port)
|
17
|
+
end
|
18
|
+
|
19
|
+
def indexed_with_elastics(options = {})
|
20
|
+
options = {
|
21
|
+
hooks: [:update, :destroy],
|
22
|
+
}.merge(options)
|
23
|
+
|
24
|
+
extend ModelSchema
|
25
|
+
include HelperMethods
|
26
|
+
extend Instrumentation
|
27
|
+
|
28
|
+
self.elastics_index_name = options[:index] if options[:index]
|
29
|
+
self.elastics_type_name = options[:type] if options[:type]
|
30
|
+
|
31
|
+
hooks = options[:hooks]
|
32
|
+
after_commit :index_elastics, on: [:create, :update] if hooks.include?(:update)
|
33
|
+
after_commit :delete_elastics, on: [:destroy] if hooks.include?(:destroy)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'httpclient'
|
2
|
+
|
3
|
+
module Elastics
|
4
|
+
class Client
|
5
|
+
HEADERS = {'Content-Type' => 'application/json'}
|
6
|
+
|
7
|
+
attr_writer :index, :type
|
8
|
+
attr_reader :client
|
9
|
+
|
10
|
+
def initialize(defaults = {})
|
11
|
+
@host = defaults[:host] || '127.0.0.1'
|
12
|
+
@port = defaults[:port] || 9200
|
13
|
+
@index = defaults[:index]
|
14
|
+
@type = defaults[:type]
|
15
|
+
@client = HTTPClient.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def debug!(dev = STDOUT)
|
19
|
+
@client.debug_dev = dev
|
20
|
+
end
|
21
|
+
|
22
|
+
def debug_off!
|
23
|
+
@client.debug_dev = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_index(index, type = nil)
|
27
|
+
@index = index || nil
|
28
|
+
@type = type || nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def uri(params)
|
32
|
+
str = "http://#{@host}:#{@port}"
|
33
|
+
if index = params[:index] || @index
|
34
|
+
str += "/#{index}"
|
35
|
+
type = params[:type] || @type
|
36
|
+
str += "/#{type}" if type
|
37
|
+
end
|
38
|
+
path = params[:id]
|
39
|
+
str += "/#{path}" if path
|
40
|
+
str
|
41
|
+
end
|
42
|
+
|
43
|
+
def request(params)
|
44
|
+
http_method = params[:method] || :get
|
45
|
+
body = params[:data].try!(:to_json)
|
46
|
+
res = @client.request(http_method, uri(params), params[:query], body, HEADERS)
|
47
|
+
status = res.status
|
48
|
+
return JSON.parse(res.body) if 300 > status
|
49
|
+
if 404 == status
|
50
|
+
message = JSON.parse(res.body)['error'] rescue 'Not found'
|
51
|
+
raise NotFound, message
|
52
|
+
end
|
53
|
+
raise Error.new(res.reason)
|
54
|
+
end
|
55
|
+
|
56
|
+
# shortcuts
|
57
|
+
[:put, :post, :delete].each do |method|
|
58
|
+
define_method(method) do |params|
|
59
|
+
params[:method] = method
|
60
|
+
request params
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def get(params)
|
65
|
+
params = {id: params} unless params.is_a?(Hash)
|
66
|
+
params[:method] = :get
|
67
|
+
request(params)
|
68
|
+
end
|
69
|
+
|
70
|
+
def set(id, data)
|
71
|
+
request(id: id, data: data, method: :put)
|
72
|
+
end
|
73
|
+
|
74
|
+
def put_mapping(params)
|
75
|
+
params[:id] = :_mapping
|
76
|
+
params[:method] = :put
|
77
|
+
request(params)
|
78
|
+
end
|
79
|
+
|
80
|
+
def search(params)
|
81
|
+
params[:id] = :_search
|
82
|
+
params[:method] = :post
|
83
|
+
request(params)
|
84
|
+
end
|
85
|
+
|
86
|
+
def index(params)
|
87
|
+
params[:id] ? put(params) : post(params)
|
88
|
+
end
|
89
|
+
|
90
|
+
def index_exists?(index)
|
91
|
+
get(index: index, type: nil, id: :_mapping)
|
92
|
+
true
|
93
|
+
rescue NotFound
|
94
|
+
false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Elastics
|
2
|
+
module QueryHelper
|
3
|
+
def normalize_filters(filters)
|
4
|
+
return filters unless filters.is_a?(Array)
|
5
|
+
return filters[0] if 2 > filters.size
|
6
|
+
{and: {filters: filters}}
|
7
|
+
end
|
8
|
+
|
9
|
+
def normalize_query(query, filters)
|
10
|
+
filter = normalize_filters filters
|
11
|
+
query ||= {match_all: {}}
|
12
|
+
return query unless filter
|
13
|
+
{filtered: {
|
14
|
+
query: query,
|
15
|
+
filter: filter,
|
16
|
+
}}
|
17
|
+
end
|
18
|
+
|
19
|
+
def terms_query(field, val, options = {})
|
20
|
+
if val.is_a?(Array)
|
21
|
+
{terms: {field => val}.merge(options)}
|
22
|
+
else
|
23
|
+
result = {term: {field => val}}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'elastics/active_record'
|
2
|
+
|
3
|
+
module Elastics
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
initializer 'elastics.configure_rails_initialization' do
|
6
|
+
::ActiveRecord::Base.extend Elastics::ActiveRecord
|
7
|
+
unless ::ActiveRecord::LogSubscriber < ActiveRecord::LogSubscriber
|
8
|
+
::ActiveRecord::LogSubscriber.send :include, ActiveRecord::LogSubscriber
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
rake_tasks do
|
13
|
+
load 'tasks/elastics.rake'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Elastics::Railtie.run_initializers
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Elastics
|
2
|
+
module Tasks
|
3
|
+
module Indices
|
4
|
+
attr_writer :indices_path
|
5
|
+
|
6
|
+
def indices_paths
|
7
|
+
@indices_paths ||= base_paths.map { |x| File.join x, 'indices' }
|
8
|
+
end
|
9
|
+
|
10
|
+
def indices_settings
|
11
|
+
@indices_settings ||= indices_paths.map { |path| Dir["#{path}/*.yml"] }.
|
12
|
+
flatten.sort.
|
13
|
+
each_with_object({}) do |file, hash|
|
14
|
+
name = File.basename file, '.yml'
|
15
|
+
data = YAML.load_file(file)
|
16
|
+
name = "#{config[:index_prefix]}#{name}"
|
17
|
+
hash[name] = data[Rails.env] || data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def indices
|
22
|
+
@indices ||= config[:index] ? [config[:index]] : indices_settings.keys
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_indices
|
26
|
+
indices.each do |index|
|
27
|
+
log "Delete index #{index}"
|
28
|
+
client.delete index: index rescue NotFound
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_indices
|
33
|
+
indices.each do |index|
|
34
|
+
log "Create index #{index}"
|
35
|
+
unless client.index_exists?(index)
|
36
|
+
client.put(index: index, data: indices_settings[index])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Elastics
|
2
|
+
module Tasks
|
3
|
+
module Mappings
|
4
|
+
attr_writer :mappings_path
|
5
|
+
|
6
|
+
def mappings_paths
|
7
|
+
@mappings_paths ||= base_paths.map { |x| File.join x, 'mappings' }
|
8
|
+
end
|
9
|
+
|
10
|
+
def put_mappings
|
11
|
+
mappings.each do |type, mapping|
|
12
|
+
index = index_for_type(type)
|
13
|
+
log "Put mapping #{index}/#{type}"
|
14
|
+
client.put_mapping index: index, type: type, data: mapping
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def mappings
|
19
|
+
@mappings ||= mappings_paths.map { |path| Dir["#{path}/*.yml"] }.
|
20
|
+
flatten.sort.
|
21
|
+
each_with_object({}) do |file, hash|
|
22
|
+
name = File.basename file, '.yml'
|
23
|
+
hash[name] = YAML.load_file(file)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def types
|
28
|
+
@types ||= mappings.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def indices
|
32
|
+
@indices ||= (super + types.map { |type| index_for_type(type) }).uniq
|
33
|
+
end
|
34
|
+
|
35
|
+
def index_for_type(type)
|
36
|
+
config[:index] || "#{config[:index_prefix]}#{type}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Elastics
|
2
|
+
module Tasks
|
3
|
+
require 'elastics/tasks/indices'
|
4
|
+
include Indices
|
5
|
+
|
6
|
+
require 'elastics/tasks/mappings'
|
7
|
+
include Mappings
|
8
|
+
|
9
|
+
extend self
|
10
|
+
|
11
|
+
attr_writer :base_paths, :client, :config
|
12
|
+
|
13
|
+
def base_paths
|
14
|
+
@base_paths ||= [File.join(Rails.root, 'db', 'elastics')]
|
15
|
+
end
|
16
|
+
|
17
|
+
def migrate(options = {})
|
18
|
+
delete_indices if options[:flush]
|
19
|
+
create_indices
|
20
|
+
put_mappings
|
21
|
+
end
|
22
|
+
|
23
|
+
def client
|
24
|
+
@client ||= ::ActiveRecord::Base.elastics
|
25
|
+
end
|
26
|
+
|
27
|
+
def config
|
28
|
+
@config ||= ::ActiveRecord::Base.elastics_config
|
29
|
+
end
|
30
|
+
|
31
|
+
def log(*args)
|
32
|
+
Rails.logger.info(*args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/elastics.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Elastics
|
2
|
+
class Error < StandardError; end
|
3
|
+
class NotFound < Error; end
|
4
|
+
|
5
|
+
require 'elastics/client'
|
6
|
+
require 'elastics/query_helper'
|
7
|
+
|
8
|
+
autoload :Tasks, 'elastics/tasks'
|
9
|
+
|
10
|
+
extend QueryHelper
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'elastics/railtie' if defined?(Rails)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
namespace 'elastics' do
|
2
|
+
task load_config: [:environment, 'db:load_config'] do
|
3
|
+
end
|
4
|
+
|
5
|
+
desc 'Creates indices and applies mappings (Use NOFLUSH to prevent old indices from deletion)'
|
6
|
+
task migrate: :load_config do
|
7
|
+
flush = !ENV.key?('NOFLUSH')
|
8
|
+
Elastics::Tasks.migrate(flush: flush)
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Creates indices'
|
12
|
+
task create: :load_config do
|
13
|
+
Elastics::Tasks.create_indices
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Drops indices'
|
17
|
+
task delete: :load_config do
|
18
|
+
Elastics::Tasks.delete_indices
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: elastics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Max Melentiev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httpclient
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.4.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.4.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10'
|
55
|
+
description: Lightweight and extensible elasticsearch client
|
56
|
+
email:
|
57
|
+
- melentievm@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- Gemfile
|
63
|
+
- Gemfile.lock
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- elastics.gemspec
|
67
|
+
- lib/elastics.rb
|
68
|
+
- lib/elastics/active_record.rb
|
69
|
+
- lib/elastics/active_record/helper_methods.rb
|
70
|
+
- lib/elastics/active_record/instrumentation.rb
|
71
|
+
- lib/elastics/active_record/log_subscriber.rb
|
72
|
+
- lib/elastics/active_record/model_schema.rb
|
73
|
+
- lib/elastics/client.rb
|
74
|
+
- lib/elastics/query_helper.rb
|
75
|
+
- lib/elastics/railtie.rb
|
76
|
+
- lib/elastics/tasks.rb
|
77
|
+
- lib/elastics/tasks/indices.rb
|
78
|
+
- lib/elastics/tasks/mappings.rb
|
79
|
+
- lib/elastics/version.rb
|
80
|
+
- lib/tasks/elastics.rake
|
81
|
+
homepage: http://github.com/printercu/elastics-rb
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.2.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: ElasticSearch client with ActiveRecord integration
|
105
|
+
test_files: []
|