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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +15 -9
  4. data/Gemfile +5 -4
  5. data/README.md +214 -0
  6. data/elastic_record.gemspec +7 -7
  7. data/lib/elastic_record.rb +1 -0
  8. data/lib/elastic_record/callbacks.rb +46 -14
  9. data/lib/elastic_record/config.rb +1 -21
  10. data/lib/elastic_record/connection.rb +24 -14
  11. data/lib/elastic_record/errors.rb +5 -0
  12. data/lib/elastic_record/index.rb +11 -1
  13. data/lib/elastic_record/index/deferred.rb +1 -0
  14. data/lib/elastic_record/index/documents.rb +95 -18
  15. data/lib/elastic_record/index/manage.rb +0 -8
  16. data/lib/elastic_record/index/mapping.rb +1 -10
  17. data/lib/elastic_record/json.rb +29 -0
  18. data/lib/elastic_record/relation.rb +9 -5
  19. data/lib/elastic_record/relation/batches.rb +4 -40
  20. data/lib/elastic_record/relation/none.rb +0 -4
  21. data/lib/elastic_record/relation/search_methods.rb +48 -38
  22. data/lib/elastic_record/relation/value_methods.rb +2 -2
  23. data/lib/elastic_record/tasks/index.rake +2 -2
  24. data/test/dummy/.env.example +1 -0
  25. data/test/dummy/.env.test +1 -0
  26. data/test/dummy/app/models/project.rb +1 -1
  27. data/test/dummy/app/models/test_model.rb +3 -2
  28. data/test/dummy/app/models/widget.rb +3 -3
  29. data/test/dummy/config/initializers/elastic_record.rb +1 -1
  30. data/test/dummy/db/migrate/20151211225259_create_projects.rb +7 -0
  31. data/test/dummy/db/schema.rb +8 -1
  32. data/test/elastic_record/callbacks_test.rb +16 -2
  33. data/test/elastic_record/config_test.rb +1 -2
  34. data/test/elastic_record/connection_test.rb +52 -9
  35. data/test/elastic_record/index/documents_test.rb +55 -21
  36. data/test/elastic_record/index/mapping_test.rb +0 -10
  37. data/test/elastic_record/integration/active_record_test.rb +3 -3
  38. data/test/elastic_record/log_subscriber_test.rb +4 -4
  39. data/test/elastic_record/relation/batches_test.rb +5 -24
  40. data/test/elastic_record/relation/delegation_test.rb +4 -3
  41. data/test/elastic_record/relation/finder_methods_test.rb +1 -0
  42. data/test/elastic_record/relation/search_methods_test.rb +47 -45
  43. data/test/elastic_record/relation_test.rb +18 -10
  44. data/test/helper.rb +4 -3
  45. metadata +21 -12
  46. data/README.rdoc +0 -146
  47. 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
- FakeWeb.register_uri(:any, %r[/test], status: ["200", "OK"], body: ActiveSupport::JSON.encode('the' => 'response'))
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['#{ActiveSupport::JSON.encode('foo' => 'bar')}'], @logger.logged(:debug)[0]
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
- FakeWeb.register_uri(:any, %r[/widgets?v=%DB], status: ["200", "OK"], body: ActiveSupport::JSON.encode('the' => 'response', 'has %DB' => 'odd %DB stuff'))
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['#{ActiveSupport::JSON.encode('foo' => 'bar', 'escape %DB ' => 'request %DB')}'], @logger.logged(:debug)[0]
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 test_find_offset_shards
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 8, results.size
62
- results.each do |r| assert_equal 1, r.size end
63
- assert_equal ['5', '10', '15', '20', '25', '30', '35', '40'].to_set, results.flatten.to_set
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
@@ -69,6 +69,7 @@ class ElasticRecord::Relation::FinderMethodsTest < MiniTest::Test
69
69
  private
70
70
 
71
71
  def create_widgets
72
+ Widget.elastic_index.delete_all
72
73
  Widget.elastic_index.bulk_add [
73
74
  Widget.new(color: 'red', id: '05'),
74
75
  Widget.new(color: 'blue', id: '10'),
@@ -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 test_query_with_only_query
61
- relation.query!('foo')
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
- "prefix" => {
81
- "name" => "mat"
66
+ "not" => {
67
+ "prefix" => {
68
+ "name" => "Jo"
69
+ }
82
70
  }
83
71
  }
84
72
  }
85
73
  }
86
74
 
87
- assert_equal expected, relation.as_elastic['query']
75
+ assert_equal expected, scope.as_elastic['query']
88
76
  end
89
77
 
90
- def test_facet_with_arelastic
91
- relation.facet!(Widget.arelastic.facet['popular_tags'].histogram('field' => 'field_name', 'interval' => 100))
78
+ def test_filter_with_nested
79
+ scope = relation.filter.nested("contacts", "prefix" => {"contacts.name" => "Jo"})
92
80
 
93
81
  expected = {
94
- "popular_tags" => {
95
- "histogram" =>
96
- {
97
- "field" => "field_name",
98
- "interval" => 100
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, relation.as_elastic['facets']
96
+ assert_equal expected, scope.as_elastic['query']
104
97
  end
105
98
 
106
- def test_facet_bang_with_string
107
- relation.facet!('tags', 'size' => 10)
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['facets']
104
+ assert_equal expected, relation.as_elastic['query']
119
105
  end
120
106
 
121
- def test_facet_with_string
122
- faceted = relation.facet('tags', 'size' => 10)
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
- "tags" => {
126
- "terms" => {
127
- "field" => "tags",
128
- "size" => 10
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, faceted.as_elastic['facets']
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 # Widget.arelastic.facet['popular_colors'].terms('color')).facets
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", __FILE__)
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
- FakeWeb.allow_net_connect = %r[^https?://127.0.0.1]
8
+ WebMock.disable_net_connect!(allow_localhost: true)
8
9
 
9
10
  module MiniTest
10
11
  class Test
11
12
  def setup
12
- FakeWeb.clean_registry
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: 2.0.2
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: 2015-01-23 00:00:00.000000000 Z
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: 0.7.0
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: 0.7.0
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 elastic search
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.rdoc
53
+ - README.md
48
54
  files:
49
55
  - ".gitignore"
50
56
  - ".travis.yml"
51
57
  - Gemfile
52
58
  - LICENSE
53
- - README.rdoc
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.2.2
189
+ rubygems_version: 2.4.5.1
181
190
  signing_key:
182
191
  specification_version: 4
183
- summary: Use Elastic Search with your objects
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