elastic_record 2.0.2 → 3.0.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/.gitignore +1 -0
- data/.travis.yml +15 -9
- data/Gemfile +5 -4
- data/README.md +214 -0
- data/elastic_record.gemspec +7 -7
- data/lib/elastic_record.rb +1 -0
- data/lib/elastic_record/callbacks.rb +46 -14
- data/lib/elastic_record/config.rb +1 -21
- data/lib/elastic_record/connection.rb +24 -14
- data/lib/elastic_record/errors.rb +5 -0
- data/lib/elastic_record/index.rb +11 -1
- data/lib/elastic_record/index/deferred.rb +1 -0
- data/lib/elastic_record/index/documents.rb +95 -18
- data/lib/elastic_record/index/manage.rb +0 -8
- data/lib/elastic_record/index/mapping.rb +1 -10
- data/lib/elastic_record/json.rb +29 -0
- data/lib/elastic_record/relation.rb +9 -5
- data/lib/elastic_record/relation/batches.rb +4 -40
- data/lib/elastic_record/relation/none.rb +0 -4
- data/lib/elastic_record/relation/search_methods.rb +48 -38
- data/lib/elastic_record/relation/value_methods.rb +2 -2
- data/lib/elastic_record/tasks/index.rake +2 -2
- data/test/dummy/.env.example +1 -0
- data/test/dummy/.env.test +1 -0
- data/test/dummy/app/models/project.rb +1 -1
- data/test/dummy/app/models/test_model.rb +3 -2
- data/test/dummy/app/models/widget.rb +3 -3
- data/test/dummy/config/initializers/elastic_record.rb +1 -1
- data/test/dummy/db/migrate/20151211225259_create_projects.rb +7 -0
- data/test/dummy/db/schema.rb +8 -1
- data/test/elastic_record/callbacks_test.rb +16 -2
- data/test/elastic_record/config_test.rb +1 -2
- data/test/elastic_record/connection_test.rb +52 -9
- data/test/elastic_record/index/documents_test.rb +55 -21
- data/test/elastic_record/index/mapping_test.rb +0 -10
- data/test/elastic_record/integration/active_record_test.rb +3 -3
- data/test/elastic_record/log_subscriber_test.rb +4 -4
- data/test/elastic_record/relation/batches_test.rb +5 -24
- data/test/elastic_record/relation/delegation_test.rb +4 -3
- data/test/elastic_record/relation/finder_methods_test.rb +1 -0
- data/test/elastic_record/relation/search_methods_test.rb +47 -45
- data/test/elastic_record/relation_test.rb +18 -10
- data/test/helper.rb +4 -3
- metadata +21 -12
- data/README.rdoc +0 -146
- data/test/dummy/config/database.yml +0 -15
@@ -16,25 +16,25 @@ class ElasticRecord::LogSubscriberTest < ActiveSupport::TestCase
|
|
16
16
|
# end
|
17
17
|
|
18
18
|
def test_request_notification
|
19
|
-
|
19
|
+
stub_request(:any, '/test').to_return(status: 200, body: Oj.dump('the' => 'response'))
|
20
20
|
Widget.elastic_connection.json_get "/widgets", {'foo' => 'bar'}
|
21
21
|
|
22
22
|
wait
|
23
23
|
|
24
24
|
assert_equal 1, @logger.logged(:debug).size
|
25
25
|
assert_match /GET (.*)widgets/, @logger.logged(:debug)[0]
|
26
|
-
assert_match %r['#{
|
26
|
+
assert_match %r['#{Oj.dump('foo' => 'bar')}'], @logger.logged(:debug)[0]
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_request_notification_escaping
|
30
|
-
|
30
|
+
stub_request(:any, "#{Widget.elastic_connection.servers.first}/widgets?v=%DB").to_return(status: 200, body: Oj.dump('the' => 'response', 'has %DB' => 'odd %DB stuff'))
|
31
31
|
Widget.elastic_connection.json_get "/widgets?v=%DB", {'foo' => 'bar', 'escape %DB ' => 'request %DB'}
|
32
32
|
|
33
33
|
wait
|
34
34
|
|
35
35
|
assert_equal 1, @logger.logged(:debug).size
|
36
36
|
assert_match /GET (.*)widgets/, @logger.logged(:debug)[0]
|
37
|
-
assert_match %r['#{
|
37
|
+
assert_match %r['#{Oj.dump('foo' => 'bar', 'escape %DB ' => 'request %DB')}'], @logger.logged(:debug)[0]
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_initializes_runtime
|
@@ -50,43 +50,24 @@ class ElasticRecord::Relation::BatchesTest < MiniTest::Test
|
|
50
50
|
assert_equal [['5', '10'].to_set], results.map(&:to_set)
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
54
|
-
create_additional_widgets
|
55
|
-
|
53
|
+
def test_find_with_batch_size
|
56
54
|
results = []
|
57
55
|
Widget.elastic_relation.find_ids_in_batches(batch_size: 1) do |ids|
|
58
56
|
results << ids
|
59
57
|
end
|
60
58
|
|
61
|
-
assert_equal
|
62
|
-
results.each
|
63
|
-
assert_equal ['5', '10', '15'
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_create_scan_search
|
67
|
-
scan_search = Widget.elastic_relation.create_scan_search
|
68
|
-
|
69
|
-
assert_equal 3, scan_search.total_hits
|
70
|
-
refute_nil scan_search.scroll_id
|
71
|
-
assert_equal 3, scan_search.request_more_ids.size
|
59
|
+
assert_equal 3, results.size
|
60
|
+
results.each { |r| assert_equal 1, r.size }
|
61
|
+
assert_equal ['5', '10', '15'].to_set, results.flatten.to_set
|
72
62
|
end
|
73
63
|
|
74
64
|
private
|
75
65
|
def create_widgets
|
66
|
+
Widget.elastic_index.delete_all
|
76
67
|
Widget.elastic_index.bulk_add [
|
77
68
|
Widget.new(id: 5, color: 'red'),
|
78
69
|
Widget.new(id: 10, color: 'blue'),
|
79
70
|
Widget.new(id: 15, color: 'green'),
|
80
71
|
]
|
81
72
|
end
|
82
|
-
|
83
|
-
def create_additional_widgets
|
84
|
-
Widget.elastic_index.bulk_add [
|
85
|
-
Widget.new(id: 20, color: 'yellow'),
|
86
|
-
Widget.new(id: 25, color: 'violet'),
|
87
|
-
Widget.new(id: 30, color: 'indigo'),
|
88
|
-
Widget.new(id: 35, color: 'orange'),
|
89
|
-
Widget.new(id: 40, color: 'black'),
|
90
|
-
]
|
91
|
-
end
|
92
73
|
end
|
@@ -2,8 +2,9 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class ElasticRecord::Relation::DelegationTest < MiniTest::Test
|
4
4
|
def test_delegate_to_array
|
5
|
+
Widget.elastic_index.delete_all
|
5
6
|
Widget.elastic_index.index_document('5', color: 'red')
|
6
|
-
|
7
|
+
|
7
8
|
records = []
|
8
9
|
Widget.elastic_relation.each do |record|
|
9
10
|
records << record
|
@@ -22,6 +23,6 @@ class ElasticRecord::Relation::DelegationTest < MiniTest::Test
|
|
22
23
|
result = model.elastic_relation.filter('foo' => 'bar').do_it
|
23
24
|
|
24
25
|
expected = {"query" => {"filtered" => {"filter" => {"term" => {"foo" => "bar"}}}}}
|
25
|
-
assert_equal expected, result
|
26
|
+
assert_equal expected, result
|
26
27
|
end
|
27
|
-
end
|
28
|
+
end
|
@@ -57,80 +57,73 @@ class ElasticRecord::Relation::SearchMethodsTest < MiniTest::Test
|
|
57
57
|
assert_equal expected, relation.as_elastic['query']
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
61
|
-
relation.
|
62
|
-
|
63
|
-
expected = {"query_string" => {"query" => "foo"}}
|
64
|
-
|
65
|
-
assert_equal expected, relation.as_elastic['query']
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_query_with_both_filter_and_query
|
69
|
-
relation.query!('field' => {'name' => 'joe'})
|
70
|
-
relation.filter!(Widget.arelastic['name'].prefix "mat")
|
60
|
+
def test_filter_with_negation
|
61
|
+
scope = relation.filter.not("prefix" => {"name" => "Jo"})
|
71
62
|
|
72
63
|
expected = {
|
73
64
|
"filtered" => {
|
74
|
-
"query" => {
|
75
|
-
"field" => {
|
76
|
-
"name"=>"joe"
|
77
|
-
},
|
78
|
-
},
|
79
65
|
"filter" => {
|
80
|
-
"
|
81
|
-
"
|
66
|
+
"not" => {
|
67
|
+
"prefix" => {
|
68
|
+
"name" => "Jo"
|
69
|
+
}
|
82
70
|
}
|
83
71
|
}
|
84
72
|
}
|
85
73
|
}
|
86
74
|
|
87
|
-
assert_equal expected,
|
75
|
+
assert_equal expected, scope.as_elastic['query']
|
88
76
|
end
|
89
77
|
|
90
|
-
def
|
91
|
-
relation.
|
78
|
+
def test_filter_with_nested
|
79
|
+
scope = relation.filter.nested("contacts", "prefix" => {"contacts.name" => "Jo"})
|
92
80
|
|
93
81
|
expected = {
|
94
|
-
"
|
95
|
-
"
|
96
|
-
|
97
|
-
|
98
|
-
|
82
|
+
"filtered" => {
|
83
|
+
"filter" => {
|
84
|
+
"nested" => {
|
85
|
+
"path" => "contacts",
|
86
|
+
"filter" => {
|
87
|
+
"prefix" => {
|
88
|
+
"contacts.name" => "Jo"
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
99
92
|
}
|
100
93
|
}
|
101
94
|
}
|
102
95
|
|
103
|
-
assert_equal expected,
|
96
|
+
assert_equal expected, scope.as_elastic['query']
|
104
97
|
end
|
105
98
|
|
106
|
-
def
|
107
|
-
relation.
|
99
|
+
def test_query_with_only_query
|
100
|
+
relation.query!('foo')
|
108
101
|
|
109
|
-
expected = {
|
110
|
-
"tags" => {
|
111
|
-
"terms" => {
|
112
|
-
"field" => "tags",
|
113
|
-
"size" => 10
|
114
|
-
}
|
115
|
-
}
|
116
|
-
}
|
102
|
+
expected = {"query_string" => {"query" => "foo"}}
|
117
103
|
|
118
|
-
assert_equal expected, relation.as_elastic['
|
104
|
+
assert_equal expected, relation.as_elastic['query']
|
119
105
|
end
|
120
106
|
|
121
|
-
def
|
122
|
-
|
107
|
+
def test_query_with_both_filter_and_query
|
108
|
+
relation.query!('field' => {'name' => 'joe'})
|
109
|
+
relation.filter!(Widget.arelastic['name'].prefix "mat")
|
123
110
|
|
124
111
|
expected = {
|
125
|
-
"
|
126
|
-
"
|
127
|
-
"field" =>
|
128
|
-
|
112
|
+
"filtered" => {
|
113
|
+
"query" => {
|
114
|
+
"field" => {
|
115
|
+
"name"=>"joe"
|
116
|
+
},
|
117
|
+
},
|
118
|
+
"filter" => {
|
119
|
+
"prefix" => {
|
120
|
+
"name" => "mat"
|
121
|
+
}
|
129
122
|
}
|
130
123
|
}
|
131
124
|
}
|
132
125
|
|
133
|
-
assert_equal expected,
|
126
|
+
assert_equal expected, relation.as_elastic['query']
|
134
127
|
end
|
135
128
|
|
136
129
|
def test_aggregation_with_bang
|
@@ -171,6 +164,15 @@ class ElasticRecord::Relation::SearchMethodsTest < MiniTest::Test
|
|
171
164
|
assert_equal expected, relation.as_elastic['sort']
|
172
165
|
end
|
173
166
|
|
167
|
+
def test_search_type
|
168
|
+
relation.search_type! :count
|
169
|
+
|
170
|
+
Widget.elastic_index.index_record Widget.new(color: 'red')
|
171
|
+
|
172
|
+
assert_equal 1, relation.count
|
173
|
+
assert_equal [], relation.to_ids
|
174
|
+
end
|
175
|
+
|
174
176
|
def test_reverse_order
|
175
177
|
relation.order! 'foo' => {'missing' => '_last'}
|
176
178
|
relation.order! 'bar' => 'desc'
|
@@ -2,23 +2,16 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class ElasticRecord::RelationTest < MiniTest::Test
|
4
4
|
def test_count
|
5
|
+
original_count = Widget.elastic_relation.count
|
5
6
|
create_widgets [Widget.new(id: 5, color: 'red'), Widget.new(id: 10, color: 'blue')]
|
6
7
|
|
7
|
-
assert_equal 2, Widget.elastic_relation.count
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_facets
|
11
|
-
create_widgets [Widget.new(id: 5, color: 'red'), Widget.new(id: 10, color: 'blue')]
|
12
|
-
|
13
|
-
facets = Widget.elastic_relation.facet(Widget.arelastic.facet['popular_colors'].terms('color')).facets
|
14
|
-
|
15
|
-
assert_equal 2, facets['popular_colors']['total']
|
8
|
+
assert_equal 2, Widget.elastic_relation.count - original_count
|
16
9
|
end
|
17
10
|
|
18
11
|
def test_aggregations
|
19
12
|
create_widgets [Widget.new(id: 5, color: 'red'), Widget.new(id: 10, color: 'blue')]
|
20
13
|
|
21
|
-
aggregations = Widget.elastic_relation.aggregate('popular_colors' => {'terms' => {'field' => 'color'}}).aggregations
|
14
|
+
aggregations = Widget.elastic_relation.aggregate('popular_colors' => {'terms' => {'field' => 'color'}}).aggregations
|
22
15
|
|
23
16
|
assert_equal 2, aggregations['popular_colors']['buckets'].size
|
24
17
|
assert_equal %w(red blue).to_set, aggregations['popular_colors']['buckets'].map { |bucket| bucket['key'] }.to_set
|
@@ -35,12 +28,14 @@ class ElasticRecord::RelationTest < MiniTest::Test
|
|
35
28
|
end
|
36
29
|
|
37
30
|
def test_to_ids
|
31
|
+
Widget.elastic_index.delete_all
|
38
32
|
create_widgets [Widget.new(id: 5, color: 'red'), Widget.new(id: 10, color: 'blue')]
|
39
33
|
|
40
34
|
assert_equal ['5', '10'].to_set, Widget.elastic_relation.to_ids.to_set
|
41
35
|
end
|
42
36
|
|
43
37
|
def test_to_a
|
38
|
+
Widget.elastic_index.delete_all
|
44
39
|
create_widgets [Widget.new(id: 5, color: 'red'), Widget.new(id: 10, color: 'blue')]
|
45
40
|
|
46
41
|
array = Widget.elastic_relation.to_a
|
@@ -49,6 +44,19 @@ class ElasticRecord::RelationTest < MiniTest::Test
|
|
49
44
|
assert array.first.is_a?(Widget)
|
50
45
|
end
|
51
46
|
|
47
|
+
def test_delete_all
|
48
|
+
project_red = Project.create! name: 'Red'
|
49
|
+
project_blue = Project.create! name: 'Blue'
|
50
|
+
|
51
|
+
Project.elastic_relation.filter(name: 'Red').delete_all
|
52
|
+
|
53
|
+
assert_nil Project.find_by(id: project_red.id)
|
54
|
+
assert_equal 0, Project.elastic_relation.filter(name: 'Red').count
|
55
|
+
|
56
|
+
refute_nil Project.find_by(id: project_blue.id)
|
57
|
+
assert_equal 1, Project.elastic_relation.filter(name: 'Blue').count
|
58
|
+
end
|
59
|
+
|
52
60
|
def test_equal
|
53
61
|
create_widgets [Widget.new(id: 5, color: 'red'), Widget.new(id: 10, color: 'blue')]
|
54
62
|
|
data/test/helper.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
ENV["RAILS_ENV"] = "test"
|
2
2
|
|
3
|
-
require File.expand_path("../../test/dummy/config/environment.rb",
|
3
|
+
require File.expand_path("../../test/dummy/config/environment.rb", __FILE__)
|
4
4
|
|
5
5
|
require 'minitest/autorun'
|
6
|
+
require 'webmock/minitest'
|
6
7
|
|
7
|
-
|
8
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
8
9
|
|
9
10
|
module MiniTest
|
10
11
|
class Test
|
11
12
|
def setup
|
12
|
-
|
13
|
+
WebMock.reset!
|
13
14
|
|
14
15
|
ElasticRecord::Config.models.each do |model|
|
15
16
|
model.elastic_index.enable_deferring!
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastic_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Infogroup
|
@@ -9,48 +9,54 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-04-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: arelastic
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.1'
|
18
21
|
- - ">="
|
19
22
|
- !ruby/object:Gem::Version
|
20
|
-
version:
|
23
|
+
version: 1.1.2
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
24
27
|
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '1.1'
|
25
31
|
- - ">="
|
26
32
|
- !ruby/object:Gem::Version
|
27
|
-
version:
|
33
|
+
version: 1.1.2
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: activemodel
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
31
37
|
requirements:
|
32
|
-
- - "
|
38
|
+
- - "~>"
|
33
39
|
- !ruby/object:Gem::Version
|
34
40
|
version: '0'
|
35
41
|
type: :runtime
|
36
42
|
prerelease: false
|
37
43
|
version_requirements: !ruby/object:Gem::Requirement
|
38
44
|
requirements:
|
39
|
-
- - "
|
45
|
+
- - "~>"
|
40
46
|
- !ruby/object:Gem::Version
|
41
47
|
version: '0'
|
42
|
-
description: Find your records with
|
48
|
+
description: Find your records with Elasticsearch
|
43
49
|
email: developer@matthewhiggins.com
|
44
50
|
executables: []
|
45
51
|
extensions: []
|
46
52
|
extra_rdoc_files:
|
47
|
-
- README.
|
53
|
+
- README.md
|
48
54
|
files:
|
49
55
|
- ".gitignore"
|
50
56
|
- ".travis.yml"
|
51
57
|
- Gemfile
|
52
58
|
- LICENSE
|
53
|
-
- README.
|
59
|
+
- README.md
|
54
60
|
- Rakefile
|
55
61
|
- elastic_record.gemspec
|
56
62
|
- lib/elastic_record.rb
|
@@ -67,6 +73,7 @@ files:
|
|
67
73
|
- lib/elastic_record/index/percolator.rb
|
68
74
|
- lib/elastic_record/index/settings.rb
|
69
75
|
- lib/elastic_record/index/warmer.rb
|
76
|
+
- lib/elastic_record/json.rb
|
70
77
|
- lib/elastic_record/log_subscriber.rb
|
71
78
|
- lib/elastic_record/lucene.rb
|
72
79
|
- lib/elastic_record/model.rb
|
@@ -83,6 +90,8 @@ files:
|
|
83
90
|
- lib/elastic_record/relation/value_methods.rb
|
84
91
|
- lib/elastic_record/searching.rb
|
85
92
|
- lib/elastic_record/tasks/index.rake
|
93
|
+
- test/dummy/.env.example
|
94
|
+
- test/dummy/.env.test
|
86
95
|
- test/dummy/README.rdoc
|
87
96
|
- test/dummy/Rakefile
|
88
97
|
- test/dummy/app/assets/images/.keep
|
@@ -106,7 +115,6 @@ files:
|
|
106
115
|
- test/dummy/config.ru
|
107
116
|
- test/dummy/config/application.rb
|
108
117
|
- test/dummy/config/boot.rb
|
109
|
-
- test/dummy/config/database.yml
|
110
118
|
- test/dummy/config/elasticsearch.yml
|
111
119
|
- test/dummy/config/environment.rb
|
112
120
|
- test/dummy/config/environments/development.rb
|
@@ -124,6 +132,7 @@ files:
|
|
124
132
|
- test/dummy/config/locales/en.yml
|
125
133
|
- test/dummy/config/routes.rb
|
126
134
|
- test/dummy/config/secrets.yml
|
135
|
+
- test/dummy/db/migrate/20151211225259_create_projects.rb
|
127
136
|
- test/dummy/db/schema.rb
|
128
137
|
- test/dummy/lib/assets/.keep
|
129
138
|
- test/dummy/log/.keep
|
@@ -177,8 +186,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
186
|
version: 1.8.11
|
178
187
|
requirements: []
|
179
188
|
rubyforge_project:
|
180
|
-
rubygems_version: 2.
|
189
|
+
rubygems_version: 2.4.5.1
|
181
190
|
signing_key:
|
182
191
|
specification_version: 4
|
183
|
-
summary:
|
192
|
+
summary: An Elasticsearch querying ORM
|
184
193
|
test_files: []
|
data/README.rdoc
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
= ElasticRecord
|
2
|
-
{<img src="https://secure.travis-ci.org/data-axle/elastic_record.png?rvm=2.0.0" />}[http://travis-ci.org/data-axle/elastic_record]
|
3
|
-
{<img src="https://codeclimate.com/github/data-axle/elastic_record.png" />}[https://codeclimate.com/github/data-axle/elastic_record]
|
4
|
-
|
5
|
-
ElasticRecord is an elasticsearch ORM.
|
6
|
-
|
7
|
-
== Setup
|
8
|
-
|
9
|
-
The usual Gemfile addition:
|
10
|
-
|
11
|
-
gem 'elastic_record'
|
12
|
-
|
13
|
-
|
14
|
-
Include ElasticRecord into your model:
|
15
|
-
|
16
|
-
class Product < ActiveRecord::Base
|
17
|
-
include ElasticRecord::Model
|
18
|
-
end
|
19
|
-
|
20
|
-
== Searching
|
21
|
-
|
22
|
-
ElasticRecord adds the method 'elastic_search' to your models. It works similar to active_record scoping:
|
23
|
-
|
24
|
-
search = Product.elastic_search
|
25
|
-
|
26
|
-
=== Filtering
|
27
|
-
|
28
|
-
If a simple hash is passed into filter, a term or terms query is created:
|
29
|
-
|
30
|
-
search.filter(color: 'red') # Creates a 'term' filter
|
31
|
-
search.filter(color: %w(red blue)) # Creates a 'terms' filter
|
32
|
-
search.filter(color: nil) # Creates a 'missing' filter
|
33
|
-
|
34
|
-
If a hash containing hashes is passed into filter, it is used directly as a filter DSL expression:
|
35
|
-
|
36
|
-
search.filter(prefix: { name: "Sca" }) # Creates a prefix filter
|
37
|
-
|
38
|
-
An Arelastic object can also be passed in, working similarily to Arel:
|
39
|
-
|
40
|
-
# Name starts with 'Sca'
|
41
|
-
search.filter(Product.arelastic[:name].prefix("Sca"))
|
42
|
-
|
43
|
-
# Name does not start with 'Sca'
|
44
|
-
search.filter(Product.arelastic[:name].prefix("Sca").negated)
|
45
|
-
|
46
|
-
# Size is greater than 5
|
47
|
-
search.filter(Product.arelastic[:size].gt(5))
|
48
|
-
|
49
|
-
# Name is 'hola' or name is missing
|
50
|
-
search.filter(Product.arelastic[:name].eq("hola").or(Product.arelastic[:name].missing))
|
51
|
-
|
52
|
-
Helpful Arel builders can be found at https://github.com/matthuhiggins/arelastic/blob/master/lib/arelastic/builders/filter.rb.
|
53
|
-
|
54
|
-
=== Querying
|
55
|
-
|
56
|
-
To create a query string, pass a string to search.query:
|
57
|
-
|
58
|
-
search.query("red AND fun*") # Creates {query_string: {"red AND fun*"}}
|
59
|
-
|
60
|
-
Complex queries are done using either a hash or an arelastic object:
|
61
|
-
|
62
|
-
search.query(match: {description: "amazing"})
|
63
|
-
|
64
|
-
=== Ordering
|
65
|
-
|
66
|
-
search.order(:price) # sort by price
|
67
|
-
search.order(:color, :price) # sort by color, then price
|
68
|
-
search.order(price: :desc) # sort by price in descending order
|
69
|
-
|
70
|
-
=== Offsets and Limits
|
71
|
-
|
72
|
-
To change the 'size' and 'from' values of a query, use offset and limit:
|
73
|
-
|
74
|
-
search.limit(40).offset(80) # Creates a query with {size: 40, from: 80}
|
75
|
-
|
76
|
-
=== Aggregations
|
77
|
-
|
78
|
-
Aggregations are added with the aggregate method:
|
79
|
-
|
80
|
-
search.aggregate('popular_colors' => {'terms' => {'field' => 'color'}})
|
81
|
-
|
82
|
-
It is important to note that adding aggregations to a query is different than retrieving the results of the query:
|
83
|
-
|
84
|
-
search = search.aggregate('popular_colors' => {'terms' => {'field' => 'color'}})
|
85
|
-
search.aggregations
|
86
|
-
#=> {"popular_colors" => {"buckets" => ...}}
|
87
|
-
|
88
|
-
=== Getting Results
|
89
|
-
|
90
|
-
A search object behaves similar to an active_record scope, implementing a few methods of its own and delegating the rest to Array, and your class.
|
91
|
-
|
92
|
-
search.count # Return the number of search results
|
93
|
-
search.first # Limit results to 1 and return the first result or nil
|
94
|
-
search.find(id) # Add an ids filter to the existing query
|
95
|
-
search.as_elastic # Return the json hash that will be sent to elastic search.
|
96
|
-
|
97
|
-
The search object behaves like an array when necessary:
|
98
|
-
|
99
|
-
search.each do |product|
|
100
|
-
...
|
101
|
-
end
|
102
|
-
|
103
|
-
Class methods can be executed within scopes:
|
104
|
-
|
105
|
-
class Product
|
106
|
-
def self.increase_prices
|
107
|
-
all.each do { |product| product.increment(:price, 10) }
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Increase the price of all red products by $10.
|
112
|
-
Product.filter(color: 'red').increase_prices
|
113
|
-
|
114
|
-
== Configuration
|
115
|
-
|
116
|
-
While elastic search automatically maps fields, you may wish to override the defaults:
|
117
|
-
|
118
|
-
class Product < ActiveRecord::Base
|
119
|
-
elastic_index.configure do
|
120
|
-
property :status, type: "string", index: "not_analyzed"
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
You can also directly access Product.elastic_index.mapping and Product.elastic_index.settings:
|
125
|
-
|
126
|
-
class Product
|
127
|
-
elastic_index.mapping = {
|
128
|
-
properties: {
|
129
|
-
name: {type: "string", index: "analyzed"}
|
130
|
-
status: {type: "string", index: "not_analyzed"}
|
131
|
-
}
|
132
|
-
}
|
133
|
-
end
|
134
|
-
|
135
|
-
Create the index:
|
136
|
-
|
137
|
-
rake index:create
|
138
|
-
|
139
|
-
== Index Administration
|
140
|
-
|
141
|
-
Core and Index APIs can be accessed with Product.elastic_index. Some examples include:
|
142
|
-
|
143
|
-
Production.elastic_index.create_and_deploy # Create a new index
|
144
|
-
Production.elastic_index.reset # Delete related indexes and deploy a new one
|
145
|
-
Production.elastic_index.refresh # Call the refresh API
|
146
|
-
Production.elastic_index.get_mapping # Get the index mapping defined by elastic search
|