elasticsearch-model 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
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