elasticsearch-model 0.1.8 → 0.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a357cdf1cb6d365afa38ed6631734804545d9cac
4
- data.tar.gz: d11d799cc4c42be14d094e4561ca826f235d8399
3
+ metadata.gz: e6ee0c4e1aa23d578d305367880c00683f8722eb
4
+ data.tar.gz: e55f679c7973d5381225ca46514dd3d901a65aa4
5
5
  SHA512:
6
- metadata.gz: c6608ecda81dc60edd8a18e814ad2baa758d879ed861b9e413b9123c91c648037d719635c7875a4e95e0199dfdad660a34297a4fa759e00eec23c0bf2eefcde3
7
- data.tar.gz: 34e2112aa52d77b7b8d3fd688f11618cf2aa34634004217c613b31e65cc3b7cbd884b2614cdfb3b63d60e68ec9b2e4b0a3ff664b142287d170d9097cb9318530
6
+ metadata.gz: e1bb3398d41326acb683669d4becd275f2f6bb9c4ef4ac8148d810c056d8e59df3ee0647f0dabaeb681d29cd94eff8fee7498fbc09cd3ec91a9abd2986bce953
7
+ data.tar.gz: 7c7f7e24165e04f86494f5458944155cfa4c36f1e15acd58ede28d27372172885f74c74d1af16d6786960c0402eb0f58a24f223b58a3f865a61cb4a9f5851878
@@ -1,3 +1,11 @@
1
+ ## 0.1.9
2
+
3
+ * Added a `suggest` method to wrap the suggestions in response
4
+ * Added the `:includes` option to Adapter::ActiveRecord::Records for eagerly loading associated models
5
+ * Delegated `max_pages` method properly for Kaminari's `next_page`
6
+ * Fixed `#dup` behaviour for Elasticsearch::Model
7
+ * Fixed typos in the README and examples
8
+
1
9
  ## 0.1.8
2
10
 
3
11
  * Added "default per page" methods for pagination with multi model searches
data/README.md CHANGED
@@ -229,7 +229,7 @@ response.records.records.class
229
229
  # => ActiveRecord::Relation::ActiveRecord_Relation_Article
230
230
  ```
231
231
 
232
- The ordering of the records by score will be preserved, unless you explicitely specify a different
232
+ The ordering of the records by score will be preserved, unless you explicitly specify a different
233
233
  order in your model query language:
234
234
 
235
235
  ```ruby
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_dependency "hashie"
29
29
 
30
30
  s.add_development_dependency "bundler", "~> 1.3"
31
- s.add_development_dependency "rake"
31
+ s.add_development_dependency "rake", "< 11.0"
32
32
 
33
33
  s.add_development_dependency "elasticsearch-extensions"
34
34
 
@@ -10,3 +10,4 @@ gemspec path: '../'
10
10
  gem 'activemodel', '>= 3.0'
11
11
  gem 'activerecord', '~> 3.2'
12
12
  gem 'mongoid', '>= 3.0'
13
+ gem 'sqlite3'
@@ -9,3 +9,4 @@ gemspec path: '../'
9
9
 
10
10
  gem 'activemodel', '~> 4'
11
11
  gem 'activerecord', '~> 4'
12
+ gem 'sqlite3'
@@ -31,6 +31,7 @@ require 'elasticsearch/model/response/result'
31
31
  require 'elasticsearch/model/response/results'
32
32
  require 'elasticsearch/model/response/records'
33
33
  require 'elasticsearch/model/response/pagination'
34
+ require 'elasticsearch/model/response/suggestions'
34
35
 
35
36
  require 'elasticsearch/model/ext/active_record'
36
37
 
@@ -10,10 +10,17 @@ module Elasticsearch
10
10
  lambda { |klass| !!defined?(::ActiveRecord::Base) && klass.respond_to?(:ancestors) && klass.ancestors.include?(::ActiveRecord::Base) }
11
11
 
12
12
  module Records
13
+ attr_writer :options
14
+
15
+ def options
16
+ @options ||= {}
17
+ end
18
+
13
19
  # Returns an `ActiveRecord::Relation` instance
14
20
  #
15
21
  def records
16
22
  sql_records = klass.where(klass.primary_key => ids)
23
+ sql_records = sql_records.includes(self.options[:includes]) if self.options[:includes]
17
24
 
18
25
  # Re-order records based on the order from Elasticsearch hits
19
26
  # by redefining `to_a`, unless the user has called `order()`
@@ -84,7 +84,7 @@ module Elasticsearch
84
84
  #
85
85
  # class Article
86
86
  # # ...
87
- # def enrich(batch)
87
+ # def self.enrich(batch)
88
88
  # batch.each do |item|
89
89
  # item.metadata = MyAPI.get_metadata(item.id)
90
90
  # end
@@ -92,7 +92,7 @@ module Elasticsearch
92
92
  # end
93
93
  # end
94
94
  #
95
- # Article.import preprocess: enrich
95
+ # Article.import preprocess: :enrich
96
96
  #
97
97
  # @example Return an array of error elements instead of the number of errors, eg.
98
98
  # to try importing these records again
@@ -52,7 +52,7 @@ module Elasticsearch
52
52
 
53
53
  if block_given?
54
54
  @mapping[name][:type] ||= 'object'
55
- properties = TYPES_WITH_EMBEDDED_PROPERTIES.include?(@mapping[name][:type]) ? :properties : :fields
55
+ properties = TYPES_WITH_EMBEDDED_PROPERTIES.include?(@mapping[name][:type].to_s) ? :properties : :fields
56
56
 
57
57
  @mapping[name][properties] ||= {}
58
58
 
@@ -66,6 +66,15 @@ module Elasticsearch
66
66
  end
67
67
  end
68
68
 
69
+ # @overload dup
70
+ #
71
+ # Returns a copy of this object. Resets the __elasticsearch__ proxy so
72
+ # the duplicate will build its own proxy.
73
+ def initialize_dup(_)
74
+ @__elasticsearch__ = nil
75
+ super
76
+ end
77
+
69
78
  # Common module for the proxy classes
70
79
  #
71
80
  module Base
@@ -44,8 +44,8 @@ module Elasticsearch
44
44
  #
45
45
  # @return [Records]
46
46
  #
47
- def records
48
- @records ||= Records.new(klass, self)
47
+ def records(options = {})
48
+ @records ||= Records.new(klass, self, options)
49
49
  end
50
50
 
51
51
  # Returns the "took" time
@@ -71,6 +71,12 @@ module Elasticsearch
71
71
  def aggregations
72
72
  response['aggregations'] ? Hashie::Mash.new(response['aggregations']) : nil
73
73
  end
74
+
75
+ # Returns a Hashie::Mash of the suggestions
76
+ #
77
+ def suggestions
78
+ Suggestions.new(response['suggest'])
79
+ end
74
80
  end
75
81
  end
76
82
  end
@@ -20,8 +20,8 @@ module Elasticsearch
20
20
  Elasticsearch::Model::Response::Results.__send__ :include, ::Kaminari::PageScopeMethods
21
21
  Elasticsearch::Model::Response::Records.__send__ :include, ::Kaminari::PageScopeMethods
22
22
 
23
- Elasticsearch::Model::Response::Results.__send__ :delegate, :limit_value, :offset_value, :total_count, to: :response
24
- Elasticsearch::Model::Response::Records.__send__ :delegate, :limit_value, :offset_value, :total_count, to: :response
23
+ Elasticsearch::Model::Response::Results.__send__ :delegate, :limit_value, :offset_value, :total_count, :max_pages, to: :response
24
+ Elasticsearch::Model::Response::Records.__send__ :delegate, :limit_value, :offset_value, :total_count, :max_pages, to: :response
25
25
 
26
26
  base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
27
27
  # Define the `page` Kaminari method
@@ -12,6 +12,8 @@ module Elasticsearch
12
12
 
13
13
  delegate :each, :empty?, :size, :slice, :[], :to_a, :to_ary, to: :records
14
14
 
15
+ attr_accessor :options
16
+
15
17
  include Base
16
18
 
17
19
  # @see Base#initialize
@@ -25,6 +27,7 @@ module Elasticsearch
25
27
  metaclass = class << self; self; end
26
28
  metaclass.__send__ :include, adapter.records_mixin
27
29
 
30
+ self.options = options
28
31
  self
29
32
  end
30
33
 
@@ -0,0 +1,13 @@
1
+ module Elasticsearch
2
+ module Model
3
+ module Response
4
+
5
+ class Suggestions < Hashie::Mash
6
+ def terms
7
+ self.to_a.map { |k,v| v.first['options'] }.flatten.map {|v| v['text']}.uniq
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Elasticsearch
2
2
  module Model
3
- VERSION = "0.1.8"
3
+ VERSION = "0.1.9"
4
4
  end
5
5
  end
@@ -133,11 +133,16 @@ module Elasticsearch
133
133
  # Include the search integration
134
134
  #
135
135
  Post.__send__ :include, Searchable
136
+ Comment.__send__ :include, Elasticsearch::Model
137
+ Comment.__send__ :include, Elasticsearch::Model::Callbacks
136
138
 
137
- # ----- Reset the index -----------------------------------------------------------------
139
+ # ----- Reset the indices -----------------------------------------------------------------
138
140
 
139
141
  Post.delete_all
140
142
  Post.__elasticsearch__.create_index! force: true
143
+
144
+ Comment.delete_all
145
+ Comment.__elasticsearch__.create_index! force: true
141
146
  end
142
147
 
143
148
  should "index and find a document" do
@@ -300,6 +305,20 @@ module Elasticsearch
300
305
  assert_equal 0, Post.search('categories:One').size
301
306
  assert_equal 1, Post.search('categories:Updated').size
302
307
  end
308
+
309
+ should "eagerly load associated records" do
310
+ post_1 = Post.create(title: 'One')
311
+ post_2 = Post.create(title: 'Two')
312
+ post_1.comments.create text: 'First comment'
313
+ post_1.comments.create text: 'Second comment'
314
+
315
+ Comment.__elasticsearch__.refresh_index!
316
+
317
+ records = Comment.search('first').records(includes: :post)
318
+
319
+ assert records.first.association(:post).loaded?, "The associated Post should be eagerly loaded"
320
+ assert_equal 'One', records.first.post.title
321
+ end
303
322
  end
304
323
 
305
324
  end
@@ -22,11 +22,18 @@ module Elasticsearch
22
22
 
23
23
  settings index: { number_of_shards: 1, number_of_replicas: 0 } do
24
24
  mapping do
25
- indexes :title, type: 'string', analyzer: 'snowball'
26
- indexes :body, type: 'string'
27
- indexes :created_at, type: 'date'
25
+ indexes :title, type: 'string', analyzer: 'snowball'
26
+ indexes :body, type: 'string'
27
+ indexes :created_at, type: 'date'
28
28
  end
29
29
  end
30
+
31
+ def as_indexed_json(options = {})
32
+ attributes
33
+ .symbolize_keys
34
+ .slice(:title, :body, :created_at)
35
+ .merge(suggest_title: title)
36
+ end
30
37
  end
31
38
 
32
39
  Article.delete_all
@@ -210,10 +217,15 @@ module Elasticsearch
210
217
 
211
218
  should "allow dot access to response" do
212
219
  response = Article.search query: { match: { title: { query: 'test' } } },
213
- aggregations: { dates: { date_histogram: { field: 'created_at', interval: 'hour' } } }
220
+ aggregations: { dates: { date_histogram: { field: 'created_at', interval: 'hour' } } },
221
+ suggest: { text: 'tezt', title: { term: { field: 'title', suggest_mode: 'always' } } }
214
222
 
215
223
  response.response.respond_to?(:aggregations)
216
- assert_equal 2, response.response.aggregations.dates.buckets.first.doc_count
224
+ assert_equal 2, response.aggregations.dates.buckets.first.doc_count
225
+
226
+ response.response.respond_to?(:suggest)
227
+ assert_equal 1, response.suggestions.title.first.options.size
228
+ assert_equal ['test'], response.suggestions.terms
217
229
  end
218
230
  end
219
231
 
@@ -51,6 +51,16 @@ class Elasticsearch::Model::AdapterActiveRecordTest < Test::Unit::TestCase
51
51
  instance.load
52
52
  end
53
53
 
54
+ should "load the records with its submodels when using :includes" do
55
+ klass = mock('class', primary_key: :some_key, where: @records)
56
+ @records.expects(:includes).with([:submodel]).at_least_once
57
+
58
+ instance = DummyClassForActiveRecord.new
59
+ instance.expects(:klass).returns(klass).at_least_once
60
+ instance.options[:includes] = [:submodel]
61
+ instance.records
62
+ end
63
+
54
64
  should "reorder the records based on hits order" do
55
65
  @records.instance_variable_set(:@records, @records)
56
66
 
@@ -127,6 +127,10 @@ class Elasticsearch::Model::IndexingTest < Test::Unit::TestCase
127
127
  indexes :bar
128
128
  end
129
129
 
130
+ mappings.indexes :foo_nested_as_symbol, type: :nested do
131
+ indexes :bar
132
+ end
133
+
130
134
  # Object is the default when `type` is missing and there's a block passed
131
135
  #
132
136
  assert_equal 'object', mappings.to_hash[:mytype][:properties][:foo][:type]
@@ -140,6 +144,10 @@ class Elasticsearch::Model::IndexingTest < Test::Unit::TestCase
140
144
  assert_equal 'nested', mappings.to_hash[:mytype][:properties][:foo_nested][:type]
141
145
  assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo_nested][:properties][:bar][:type]
142
146
  assert_nil mappings.to_hash[:mytype][:properties][:foo_nested][:fields]
147
+
148
+ assert_equal :nested, mappings.to_hash[:mytype][:properties][:foo_nested_as_symbol][:type]
149
+ assert_not_nil mappings.to_hash[:mytype][:properties][:foo_nested_as_symbol][:properties]
150
+ assert_nil mappings.to_hash[:mytype][:properties][:foo_nested_as_symbol][:fields]
143
151
  end
144
152
  end
145
153
 
@@ -69,6 +69,17 @@ class Elasticsearch::Model::SearchTest < Test::Unit::TestCase
69
69
  assert_equal 'insta barr', DummyProxyModel.new.__elasticsearch__.bar
70
70
  end
71
71
 
72
+ should "reset the proxy target for duplicates" do
73
+ model = DummyProxyModel.new
74
+ model_target = model.__elasticsearch__.target
75
+ duplicate = model.dup
76
+ duplicate_target = duplicate.__elasticsearch__.target
77
+
78
+ assert_not_equal model, duplicate
79
+ assert_equal model, model_target
80
+ assert_equal duplicate, duplicate_target
81
+ end
82
+
72
83
  should "return the proxy class from instance proxy" do
73
84
  assert_equal Elasticsearch::Model::Proxy::ClassMethodsProxy, DummyProxyModel.new.__elasticsearch__.class.class
74
85
  end
@@ -194,6 +194,17 @@ class Elasticsearch::Model::ResponsePaginationKaminariTest < Test::Unit::TestCas
194
194
 
195
195
  assert_equal 5, @response.page(5).results.current_page
196
196
  end
197
+
198
+ should "return previous page and next page" do
199
+ assert_equal nil, @response.page(1).results.prev_page
200
+ assert_equal 2, @response.page(1).results.next_page
201
+
202
+ assert_equal 3, @response.page(4).results.prev_page
203
+ assert_equal nil, @response.page(4).results.next_page
204
+
205
+ assert_equal 2, @response.page(3).results.prev_page
206
+ assert_equal 4, @response.page(3).results.next_page
207
+ end
197
208
  end
198
209
 
199
210
  context "records" do
@@ -207,6 +218,17 @@ class Elasticsearch::Model::ResponsePaginationKaminariTest < Test::Unit::TestCas
207
218
 
208
219
  assert_equal 5, @response.page(5).records.current_page
209
220
  end
221
+
222
+ should "return previous page and next page" do
223
+ assert_equal nil, @response.page(1).records.prev_page
224
+ assert_equal 2, @response.page(1).records.next_page
225
+
226
+ assert_equal 3, @response.page(4).records.prev_page
227
+ assert_equal nil, @response.page(4).records.next_page
228
+
229
+ assert_equal 2, @response.page(3).records.prev_page
230
+ assert_equal 4, @response.page(3).records.next_page
231
+ end
210
232
  end
211
233
  end
212
234
 
@@ -371,6 +393,17 @@ class Elasticsearch::Model::ResponsePaginationKaminariTest < Test::Unit::TestCas
371
393
 
372
394
  assert_equal 5, @response.page(5).results.current_page
373
395
  end
396
+
397
+ should "return previous page and next page" do
398
+ assert_equal nil, @response.page(1).results.prev_page
399
+ assert_equal 2, @response.page(1).results.next_page
400
+
401
+ assert_equal 3, @response.page(4).results.prev_page
402
+ assert_equal nil, @response.page(4).results.next_page
403
+
404
+ assert_equal 2, @response.page(3).results.prev_page
405
+ assert_equal 4, @response.page(3).results.next_page
406
+ end
374
407
  end
375
408
 
376
409
  context "records" do
@@ -384,6 +417,17 @@ class Elasticsearch::Model::ResponsePaginationKaminariTest < Test::Unit::TestCas
384
417
 
385
418
  assert_equal 5, @response.page(5).records.current_page
386
419
  end
420
+
421
+ should "return previous page and next page" do
422
+ assert_equal nil, @response.page(1).records.prev_page
423
+ assert_equal 2, @response.page(1).records.next_page
424
+
425
+ assert_equal 3, @response.page(4).records.prev_page
426
+ assert_equal nil, @response.page(4).records.next_page
427
+
428
+ assert_equal 2, @response.page(3).records.prev_page
429
+ assert_equal 4, @response.page(3).records.next_page
430
+ end
387
431
  end
388
432
  end
389
433
  end
@@ -8,7 +8,8 @@ class Elasticsearch::Model::ResponseTest < Test::Unit::TestCase
8
8
  end
9
9
 
10
10
  RESPONSE = { 'took' => '5', 'timed_out' => false, '_shards' => {'one' => 'OK'}, 'hits' => { 'hits' => [] },
11
- 'aggregations' => {'foo' => {'bar' => 10}}}
11
+ 'aggregations' => {'foo' => {'bar' => 10}},
12
+ 'suggest' => {'my_suggest' => [ { 'text' => 'foo', 'options' => [ { 'text' => 'Foo', 'score' => 2.0 }, { 'text' => 'Bar', 'score' => 1.0 } ] } ]}}
12
13
 
13
14
  setup do
14
15
  @search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
@@ -73,5 +74,31 @@ class Elasticsearch::Model::ResponseTest < Test::Unit::TestCase
73
74
  assert_kind_of Hashie::Mash, response.aggregations.foo
74
75
  assert_equal 10, response.aggregations.foo.bar
75
76
  end
77
+
78
+ should "access the suggest" do
79
+ @search.expects(:execute!).returns(RESPONSE)
80
+
81
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
82
+
83
+ assert_respond_to response, :suggestions
84
+ assert_kind_of Hashie::Mash, response.suggestions
85
+ assert_equal 'Foo', response.suggestions.my_suggest.first.options.first.text
86
+ end
87
+
88
+ should "return array of terms from the suggestions" do
89
+ @search.expects(:execute!).returns(RESPONSE)
90
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
91
+
92
+ assert_not_empty response.suggestions
93
+ assert_equal [ 'Foo', 'Bar' ], response.suggestions.terms
94
+ end
95
+
96
+ should "return empty array as suggest terms when there are no suggestions" do
97
+ @search.expects(:execute!).returns({})
98
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
99
+
100
+ assert_empty response.suggestions
101
+ assert_equal [], response.suggestions.terms
102
+ end
76
103
  end
77
104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticsearch-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karel Minarik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-12 00:00:00.000000000 Z
11
+ date: 2016-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: elasticsearch
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "<"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '11.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "<"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '11.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: elasticsearch-extensions
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -364,6 +364,7 @@ files:
364
364
  - lib/elasticsearch/model/response/records.rb
365
365
  - lib/elasticsearch/model/response/result.rb
366
366
  - lib/elasticsearch/model/response/results.rb
367
+ - lib/elasticsearch/model/response/suggestions.rb
367
368
  - lib/elasticsearch/model/searching.rb
368
369
  - lib/elasticsearch/model/serializing.rb
369
370
  - lib/elasticsearch/model/version.rb