elastic_record 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -6
- data/Gemfile +0 -2
- data/README.md +25 -9
- data/elastic_record.gemspec +1 -1
- data/lib/elastic_record/as_document.rb +41 -0
- data/lib/elastic_record/callbacks.rb +11 -56
- data/lib/elastic_record/connection.rb +1 -1
- data/lib/elastic_record/doctype.rb +43 -0
- data/lib/elastic_record/index/deferred.rb +13 -15
- data/lib/elastic_record/index/documents.rb +23 -13
- data/lib/elastic_record/index/manage.rb +4 -6
- data/lib/elastic_record/index/mapping.rb +7 -26
- data/lib/elastic_record/index/settings.rb +17 -2
- data/lib/elastic_record/index.rb +12 -24
- data/lib/elastic_record/model.rb +14 -4
- data/lib/elastic_record/percolator_model.rb +44 -0
- data/lib/elastic_record/relation.rb +1 -2
- data/lib/elastic_record/searching.rb +5 -1
- data/lib/elastic_record/tasks/index.rake +0 -10
- data/lib/elastic_record.rb +3 -0
- data/test/dummy/app/models/mock_model.rb +108 -0
- data/test/dummy/app/models/project.rb +1 -1
- data/test/dummy/app/models/test_model.rb +1 -102
- data/test/dummy/app/models/test_percolator_model.rb +8 -0
- data/test/dummy/app/models/widget.rb +2 -5
- data/test/dummy/app/models/widget_query.rb +14 -0
- data/test/dummy/config/environments/test.rb +3 -3
- data/test/dummy/config/initializers/elastic_record.rb +1 -1
- data/test/elastic_record/as_document_test.rb +65 -0
- data/test/elastic_record/callbacks_test.rb +6 -81
- data/test/elastic_record/config_test.rb +1 -1
- data/test/elastic_record/doctype_test.rb +45 -0
- data/test/elastic_record/index/documents_test.rb +1 -1
- data/test/elastic_record/index/mapping_test.rb +16 -13
- data/test/elastic_record/index/settings_test.rb +34 -1
- data/test/elastic_record/index_test.rb +7 -15
- data/test/elastic_record/model_test.rb +1 -7
- data/test/elastic_record/percolator_model_test.rb +54 -0
- data/test/elastic_record/relation/batches_test.rb +0 -1
- data/test/elastic_record/relation/delegation_test.rb +0 -1
- data/test/elastic_record/relation/finder_methods_test.rb +0 -1
- data/test/elastic_record/relation_test.rb +0 -2
- data/test/elastic_record/searching_test.rb +7 -0
- metadata +11 -10
- data/lib/elastic_record/index/configurator.rb +0 -18
- data/lib/elastic_record/index/percolator.rb +0 -50
- data/lib/elastic_record/index/warmer.rb +0 -24
- data/lib/elastic_record/relation/admin.rb +0 -13
- data/test/elastic_record/index/configurator_test.rb +0 -18
- data/test/elastic_record/index/percolator_test.rb +0 -45
- data/test/elastic_record/index/warmer_test.rb +0 -20
- data/test/elastic_record/relation/admin_test.rb +0 -28
@@ -1,41 +1,22 @@
|
|
1
1
|
module ElasticRecord
|
2
2
|
class Index
|
3
3
|
module Mapping
|
4
|
-
def mapping=(custom_mapping)
|
5
|
-
mapping.deep_merge!(custom_mapping)
|
6
|
-
end
|
7
|
-
|
8
4
|
def update_mapping(index_name = alias_name)
|
9
|
-
connection.json_put "/#{index_name}
|
5
|
+
connection.json_put "/#{index_name}/_mapping", mapping_body
|
10
6
|
end
|
11
7
|
|
12
8
|
def get_mapping(index_name = alias_name)
|
13
|
-
json = connection.json_get "/#{index_name}
|
9
|
+
json = connection.json_get "/#{index_name}/_mapping"
|
10
|
+
|
14
11
|
unless json.empty?
|
15
12
|
json.values.first['mappings']
|
16
13
|
end
|
17
14
|
end
|
18
15
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
_all: {
|
24
|
-
enabled: false
|
25
|
-
},
|
26
|
-
dynamic_templates: [
|
27
|
-
{
|
28
|
-
no_string_analyzing: {
|
29
|
-
match: "*",
|
30
|
-
match_mapping_type: "string",
|
31
|
-
mapping: {
|
32
|
-
type: "string",
|
33
|
-
index: "not_analyzed"
|
34
|
-
}
|
35
|
-
}
|
36
|
-
}
|
37
|
-
]
|
38
|
-
}
|
16
|
+
def mapping_body
|
17
|
+
doctypes.each_with_object({}) do |doctype, result|
|
18
|
+
result[doctype.name] = doctype.mapping
|
19
|
+
end
|
39
20
|
end
|
40
21
|
end
|
41
22
|
end
|
@@ -6,12 +6,27 @@ module ElasticRecord
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def settings
|
9
|
-
@settings ||=
|
9
|
+
@settings ||=
|
10
|
+
begin
|
11
|
+
result = {}
|
12
|
+
|
13
|
+
if (analysis = analysis_body).any?
|
14
|
+
result['analysis'] = analysis
|
15
|
+
end
|
16
|
+
|
17
|
+
result
|
18
|
+
end
|
10
19
|
end
|
11
20
|
|
12
21
|
def update_settings(index_name = alias_name)
|
13
22
|
connection.json_put "/#{index_name}/_settings", settings
|
14
23
|
end
|
24
|
+
|
25
|
+
def analysis_body
|
26
|
+
doctypes.each_with_object({}) do |doctype, result|
|
27
|
+
result.deep_merge!(doctype.analysis)
|
28
|
+
end
|
29
|
+
end
|
15
30
|
end
|
16
31
|
end
|
17
|
-
end
|
32
|
+
end
|
data/lib/elastic_record/index.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
require 'elastic_record/index/analyze'
|
2
|
-
require 'elastic_record/index/configurator'
|
3
2
|
require 'elastic_record/index/deferred'
|
4
3
|
require 'elastic_record/index/documents'
|
5
4
|
require 'elastic_record/index/manage'
|
6
5
|
require 'elastic_record/index/mapping'
|
7
|
-
require 'elastic_record/index/percolator'
|
8
6
|
require 'elastic_record/index/settings'
|
9
|
-
require 'elastic_record/index/warmer'
|
10
7
|
|
11
8
|
require 'active_support/core_ext/object/deep_dup'
|
12
9
|
|
@@ -26,30 +23,30 @@ module ElasticRecord
|
|
26
23
|
# Returns if the index exists
|
27
24
|
# [get_mapping]
|
28
25
|
# Returns the mapping currently stored by elastic search.
|
29
|
-
# [
|
26
|
+
# [update_mapping]
|
30
27
|
# Update elastic search's mapping
|
31
28
|
class Index
|
32
29
|
include Documents
|
33
30
|
include Manage
|
34
31
|
include Mapping, Settings
|
35
|
-
include Percolator, Warmer
|
36
32
|
include Analyze
|
37
33
|
include Deferred
|
38
34
|
|
39
|
-
attr_accessor :
|
35
|
+
attr_accessor :doctypes
|
40
36
|
|
41
37
|
attr_accessor :disabled
|
42
|
-
attr_accessor :
|
38
|
+
attr_accessor :model
|
43
39
|
attr_accessor :partial_updates
|
44
40
|
|
45
|
-
def initialize(
|
46
|
-
|
41
|
+
def initialize(models)
|
42
|
+
models = Array.wrap(models)
|
43
|
+
@model = models.first
|
44
|
+
@doctypes = models.map(&:doctype)
|
47
45
|
@disabled = false
|
48
46
|
end
|
49
47
|
|
50
48
|
def initialize_copy(other)
|
51
49
|
@settings = settings.deep_dup
|
52
|
-
@mapping = mapping.deep_dup
|
53
50
|
end
|
54
51
|
|
55
52
|
def alias_name=(name)
|
@@ -60,14 +57,6 @@ module ElasticRecord
|
|
60
57
|
@alias_name ||= model.base_class.name.demodulize.underscore.pluralize
|
61
58
|
end
|
62
59
|
|
63
|
-
def type=(name)
|
64
|
-
@type = name
|
65
|
-
end
|
66
|
-
|
67
|
-
def type
|
68
|
-
@type ||= model.base_class.name.demodulize.underscore
|
69
|
-
end
|
70
|
-
|
71
60
|
def disable!
|
72
61
|
@disabled = true
|
73
62
|
end
|
@@ -80,12 +69,12 @@ module ElasticRecord
|
|
80
69
|
model.elastic_connection
|
81
70
|
end
|
82
71
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
72
|
+
def get(end_path, doctype = nil, json = nil)
|
73
|
+
path = "/#{alias_name}"
|
74
|
+
path += "/#{doctype.name}" if doctype
|
75
|
+
path += "/#{end_path}"
|
86
76
|
|
87
|
-
|
88
|
-
connection.json_get "/#{alias_name}/#{type}/#{end_path}", json
|
77
|
+
connection.json_get path, json
|
89
78
|
end
|
90
79
|
|
91
80
|
private
|
@@ -93,6 +82,5 @@ module ElasticRecord
|
|
93
82
|
def new_index_name
|
94
83
|
"#{alias_name}_#{Time.now.utc.strftime('%Y%m%d_%H%M%S')}"
|
95
84
|
end
|
96
|
-
|
97
85
|
end
|
98
86
|
end
|
data/lib/elastic_record/model.rb
CHANGED
@@ -5,6 +5,7 @@ module ElasticRecord
|
|
5
5
|
extend Searching
|
6
6
|
extend ClassMethods
|
7
7
|
include Callbacks
|
8
|
+
include AsDocument
|
8
9
|
|
9
10
|
class_attribute :elastic_connection
|
10
11
|
self.elastic_connection = ElasticRecord::Connection.new(ElasticRecord::Config.servers, ElasticRecord::Config.connection_options)
|
@@ -17,17 +18,22 @@ module ElasticRecord
|
|
17
18
|
|
18
19
|
if child < child.base_class
|
19
20
|
child.elastic_index = elastic_index.dup
|
21
|
+
child.doctype = doctype.dup
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
def elastic_relation
|
24
|
-
ElasticRecord::Relation.new(self)
|
25
|
-
end
|
26
|
-
|
27
25
|
def arelastic
|
28
26
|
Arelastic::Builders::Search
|
29
27
|
end
|
30
28
|
|
29
|
+
def doctype
|
30
|
+
@doctype ||= Doctype.new(base_class.name.demodulize.underscore)
|
31
|
+
end
|
32
|
+
|
33
|
+
def doctype=(new_doctype)
|
34
|
+
@doctype = new_doctype
|
35
|
+
end
|
36
|
+
|
31
37
|
def elastic_index
|
32
38
|
@elastic_index ||= ElasticRecord::Index.new(self)
|
33
39
|
end
|
@@ -44,5 +50,9 @@ module ElasticRecord
|
|
44
50
|
def elastic_index
|
45
51
|
self.class.elastic_index
|
46
52
|
end
|
53
|
+
|
54
|
+
def doctype
|
55
|
+
self.class.doctype
|
56
|
+
end
|
47
57
|
end
|
48
58
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ElasticRecord
|
2
|
+
module PercolatorModel
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
class_attribute :percolates_model
|
6
|
+
|
7
|
+
include Model
|
8
|
+
extend ClassMethods
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def elastic_index
|
14
|
+
@elastic_index ||=
|
15
|
+
begin
|
16
|
+
index = ElasticRecord::Index.new([self, percolates_model])
|
17
|
+
index.partial_updates = false
|
18
|
+
index
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def doctype
|
23
|
+
@doctype ||= Doctype.percolator_doctype
|
24
|
+
end
|
25
|
+
|
26
|
+
def percolate(document)
|
27
|
+
query = {
|
28
|
+
"query" => {
|
29
|
+
"percolate" => {
|
30
|
+
"field" => "query",
|
31
|
+
"document_type" => percolates_model.doctype.name,
|
32
|
+
"document" => document
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
hits = elastic_index.search(query)['hits']['hits']
|
38
|
+
ids = hits.map { |hits| hits['_id'] }
|
39
|
+
|
40
|
+
where(id: ids)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'elastic_record/relation/value_methods'
|
2
|
-
require 'elastic_record/relation/admin'
|
3
2
|
require 'elastic_record/relation/batches'
|
4
3
|
require 'elastic_record/relation/delegation'
|
5
4
|
require 'elastic_record/relation/finder_methods'
|
@@ -9,7 +8,7 @@ require 'elastic_record/relation/search_methods'
|
|
9
8
|
|
10
9
|
module ElasticRecord
|
11
10
|
class Relation
|
12
|
-
include
|
11
|
+
include Batches, Delegation, FinderMethods, Merging, SearchMethods
|
13
12
|
|
14
13
|
attr_reader :klass, :values
|
15
14
|
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module ElasticRecord
|
2
2
|
module Searching
|
3
|
+
def elastic_relation
|
4
|
+
ElasticRecord::Relation.new(self)
|
5
|
+
end
|
6
|
+
|
3
7
|
def elastic_search
|
4
8
|
if current_elastic_search
|
5
9
|
current_elastic_search.clone
|
@@ -27,4 +31,4 @@ module ElasticRecord
|
|
27
31
|
Thread.current["#{self}_current_elastic_search"] = relation
|
28
32
|
end
|
29
33
|
end
|
30
|
-
end
|
34
|
+
end
|
@@ -17,11 +17,6 @@ namespace :index do
|
|
17
17
|
index = model.elastic_index
|
18
18
|
index_name = index.create_and_deploy
|
19
19
|
puts "Created #{model.name} index (#{index_name})"
|
20
|
-
|
21
|
-
if index.has_percolator
|
22
|
-
index_name = index.create_percolator_index
|
23
|
-
puts "Created #{model.name} percolator index (#{index_name})"
|
24
|
-
end
|
25
20
|
end
|
26
21
|
end
|
27
22
|
|
@@ -31,11 +26,6 @@ namespace :index do
|
|
31
26
|
index = model.elastic_index
|
32
27
|
index.delete_all
|
33
28
|
puts "Dropped #{model.name} index"
|
34
|
-
|
35
|
-
if index.has_percolator
|
36
|
-
index.delete_percolator_index
|
37
|
-
puts "Dropped #{model.name} percolator index (#{index.percolator_name})"
|
38
|
-
end
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
data/lib/elastic_record.rb
CHANGED
@@ -3,13 +3,16 @@ require 'active_support/concern'
|
|
3
3
|
require 'active_model'
|
4
4
|
|
5
5
|
module ElasticRecord
|
6
|
+
autoload :AsDocument, 'elastic_record/as_document'
|
6
7
|
autoload :Callbacks, 'elastic_record/callbacks'
|
7
8
|
autoload :Config, 'elastic_record/config'
|
8
9
|
autoload :Connection, 'elastic_record/connection'
|
10
|
+
autoload :Doctype, 'elastic_record/doctype'
|
9
11
|
autoload :Index, 'elastic_record/index'
|
10
12
|
autoload :JSON, 'elastic_record/json'
|
11
13
|
autoload :Lucene, 'elastic_record/lucene'
|
12
14
|
autoload :Model, 'elastic_record/model'
|
15
|
+
autoload :PercolatorModel, 'elastic_record/percolator_model'
|
13
16
|
autoload :Relation, 'elastic_record/relation'
|
14
17
|
autoload :Searching, 'elastic_record/searching'
|
15
18
|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Essentially a fake ActiveRecord::Base
|
2
|
+
module MockModel
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
extend ActiveModel::Naming
|
7
|
+
extend ActiveModel::Callbacks
|
8
|
+
define_model_callbacks :save, :update, :create, :destroy
|
9
|
+
|
10
|
+
include ActiveModel::Dirty
|
11
|
+
include ActiveModel::Validations
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def find(ids)
|
16
|
+
ids.map { |id| new(id: id) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def where(query)
|
20
|
+
find query[:id]
|
21
|
+
end
|
22
|
+
|
23
|
+
def primary_key
|
24
|
+
'id'
|
25
|
+
end
|
26
|
+
|
27
|
+
def base_class
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def create(attributes = {})
|
32
|
+
record = new(attributes)
|
33
|
+
record.save
|
34
|
+
record
|
35
|
+
end
|
36
|
+
|
37
|
+
def define_attributes(attributes)
|
38
|
+
define_attribute_methods attributes
|
39
|
+
|
40
|
+
attributes.each do |attribute|
|
41
|
+
define_method attribute do
|
42
|
+
instance_variable_get("@#{attribute}")
|
43
|
+
end
|
44
|
+
|
45
|
+
define_method "#{attribute}=" do |value|
|
46
|
+
send("#{attribute}_will_change!")
|
47
|
+
instance_variable_set("@#{attribute}", value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
define_method 'attributes' do
|
52
|
+
Hash[attributes.map { |attr| [attr.to_s, send(attr)] }]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize(attrs = {})
|
58
|
+
self.attributes = attrs
|
59
|
+
end
|
60
|
+
|
61
|
+
def attributes=(attrs)
|
62
|
+
attrs.each do |key, val|
|
63
|
+
send("#{key}=", val)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def id=(value)
|
68
|
+
@id = value
|
69
|
+
end
|
70
|
+
|
71
|
+
def id
|
72
|
+
@id ||= rand(10000).to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
def save
|
76
|
+
@persisted = true
|
77
|
+
callback_method = new_record? ? :create : :update
|
78
|
+
run_callbacks callback_method
|
79
|
+
end
|
80
|
+
|
81
|
+
def destroy
|
82
|
+
@destroyed = true
|
83
|
+
run_callbacks :destroy
|
84
|
+
end
|
85
|
+
|
86
|
+
def ==(other)
|
87
|
+
id == other.id
|
88
|
+
end
|
89
|
+
|
90
|
+
def changed?
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def new_record?
|
95
|
+
!@persisted
|
96
|
+
end
|
97
|
+
|
98
|
+
def persisted?
|
99
|
+
@persisted
|
100
|
+
end
|
101
|
+
|
102
|
+
def destroyed?
|
103
|
+
@destroyed
|
104
|
+
end
|
105
|
+
|
106
|
+
def reload
|
107
|
+
end
|
108
|
+
end
|