elastic_record 4.0.0 → 4.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 +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
|