elastics 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|