tire 0.5.8 → 0.6.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.
@@ -28,13 +28,6 @@ module Tire
28
28
  @value = { :range => { field => value } }
29
29
  end
30
30
 
31
- def text(field, value, options={})
32
- Tire.warn "The 'text' query has been deprecated, please use a 'match' query."
33
- query_options = { :query => value }.update(options)
34
- @value = { :text => { field => query_options } }
35
- @value
36
- end
37
-
38
31
  def string(value, options={})
39
32
  @value = { :query_string => { :query => value } }
40
33
  @value[:query_string].update(options)
@@ -98,8 +91,10 @@ module Tire
98
91
  @value
99
92
  end
100
93
 
101
- def ids(values, type)
102
- @value = { :ids => { :values => values, :type => type } }
94
+ def ids(values, type=nil)
95
+ @value = { :ids => { :values => Array(values) } }
96
+ @value[:ids].update(:type => type) if type
97
+ @value
103
98
  end
104
99
 
105
100
  def boosting(options={}, &block)
@@ -193,7 +188,10 @@ module Tire
193
188
  end
194
189
 
195
190
  def filter(type, *options)
196
- @value.update(:filter => Filter.new(type, *options).to_hash)
191
+ @value[:filter] ||= {}
192
+ @value[:filter][:and] ||= []
193
+ @value[:filter][:and] << Filter.new(type, *options).to_hash
194
+ @value
197
195
  end
198
196
 
199
197
  def query(&block)
data/lib/tire/tasks.rb CHANGED
@@ -87,11 +87,6 @@ namespace :tire do
87
87
  namespace :import do
88
88
  desc import_model_desc
89
89
  task :model do
90
- if defined?(Rails)
91
- puts "[IMPORT] Rails detected, loading environment..."
92
- Rake::Task["environment"].invoke
93
- end
94
-
95
90
  if ENV['CLASS'].to_s == ''
96
91
  puts '='*90, 'USAGE', '='*90, import_model_desc, ""
97
92
  exit(1)
@@ -121,11 +116,6 @@ namespace :tire do
121
116
 
122
117
  desc import_all_desc
123
118
  task :all do
124
- if defined?(Rails)
125
- puts "[IMPORT] Rails detected, loading environment..."
126
- Rake::Task["environment"].invoke
127
- end
128
-
129
119
  dir = ENV['DIR'].to_s != '' ? ENV['DIR'] : Rails.root.join("app/models")
130
120
  params = eval(ENV['PARAMS'].to_s) || {}
131
121
 
@@ -134,7 +124,7 @@ namespace :tire do
134
124
  require path
135
125
 
136
126
  model_filename = path[/#{Regexp.escape(dir.to_s)}\/([^\.]+).rb/, 1]
137
- klass = model_filename.classify.constantize
127
+ klass = model_filename.camelize.constantize
138
128
 
139
129
  # Skip if the class doesn't have Tire integration
140
130
  next unless klass.respond_to?(:tire)
data/lib/tire/version.rb CHANGED
@@ -1,14 +1,20 @@
1
1
  module Tire
2
- VERSION = "0.5.8"
2
+ VERSION = "0.6.0"
3
3
 
4
4
  CHANGELOG =<<-END
5
5
  IMPORTANT CHANGES LATELY:
6
6
 
7
- * Fixed, that Model::Persistence uses "string" as the default mapping type
8
- * Fixed, that Model::Persistence returns true/false for #save and #destroy operations
9
- * Fixed the `uninitialized constant HRULE` in Rake tasks
10
- * Fixed `Item#to_hash` functionality to work with Arrays
11
- * Updated the Rails application template and install instructions
12
- * Improved the test suite for Travis
7
+ * Fixed incorrect inflection in the Rake import tasks
8
+ * Added support for `geo_distance` facets
9
+ * Added support for the `custom_filters_score` query
10
+ * Added a custom strategy option to <Model.import>
11
+ * Allow the `:wrapper` option to be passed to Tire.search consistently
12
+ * Improved the Mongoid importing strategy
13
+ * Merge returned `fields` with `_source` if both are returned
14
+ * Removed the deprecated `text` query
15
+ * [FIX] Rescue HTTP client specific connection errors in MyModel#create_elasticsearch_index
16
+ * Added support for passing `version` in Tire::Index#store
17
+ * Added support for `_version_type` in Tire::Index#bulk
18
+ * Added ActiveModel::Serializers compatibility
13
19
  END
14
20
  end
@@ -79,6 +79,19 @@ module Tire
79
79
  end
80
80
  end
81
81
  end
82
+
83
+ should "take external versioning into account" do
84
+ # Tire.configure { logger STDERR, level: 'verbose' }
85
+ index = Tire.index 'bulk-test-external-versioning' do
86
+ delete
87
+ create
88
+ store id: '1', title: 'A', _version: 10, _version_type: 'external'
89
+ end
90
+
91
+ response = index.bulk_store [ { id: '1', title: 'A', _version: 0, _version_type: 'external'} ]
92
+
93
+ assert_match /VersionConflictEngineException/, MultiJson.load(response.body)['items'][0]['index']['error']
94
+ end
82
95
  end
83
96
 
84
97
  end
@@ -0,0 +1,105 @@
1
+ require 'test_helper'
2
+
3
+ module Tire
4
+
5
+ class CustomFiltersScoreQueriesIntegrationTest < Test::Unit::TestCase
6
+ include Test::Integration
7
+
8
+ context "Custom filters score queries" do
9
+
10
+ should "score the document based on a matching filter" do
11
+ s = Tire.search('articles-test') do
12
+ query do
13
+ custom_filters_score do
14
+ query { all }
15
+
16
+ # Give documents over 300 words a score of 3
17
+ filter do
18
+ filter :range, words: { gt: 300 }
19
+ boost 3
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ assert_equal 3, s.results[0]._score
26
+ assert_equal 1, s.results[1]._score
27
+ end
28
+
29
+ should "allow to use a script based boost factor" do
30
+ s = Tire.search('articles-test') do
31
+ query do
32
+ custom_filters_score do
33
+ query { all }
34
+
35
+ # Give documents over 300 words a score of 3
36
+ filter do
37
+ filter :range, words: { gt: 300 }
38
+ script 'doc.words.value * 2'
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ # p s.results.to_a.map { |r| [r.title, r.words, r._score] }
45
+
46
+ assert_equal 750, s.results[0]._score
47
+ assert_equal 1, s.results[1]._score
48
+ end
49
+
50
+ should "allow to define multiple score factors" do
51
+ s = Tire.search('articles-test') do
52
+ query do
53
+ custom_filters_score do
54
+ query { all }
55
+
56
+ # The more words a document contains, the more its score is boosted
57
+
58
+ filter do
59
+ filter :range, words: { to: 10 }
60
+ boost 1
61
+ end
62
+
63
+ filter do
64
+ filter :range, words: { to: 100 }
65
+ boost 2
66
+ end
67
+
68
+ filter do
69
+ filter :range, words: { to: 150 }
70
+ boost 3
71
+ end
72
+
73
+ filter do
74
+ filter :range, words: { to: 250 }
75
+ boost 5
76
+ end
77
+
78
+ filter do
79
+ filter :range, words: { to: 350 }
80
+ boost 7
81
+ end
82
+
83
+ filter do
84
+ filter :range, words: { from: 350 }
85
+ boost 10
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ # p s.results.to_a.map { |r| [r.title, r.words, r._score] }
92
+
93
+ assert_equal 'Three', s.results[0].title
94
+ assert_equal 375, s.results[0].words
95
+ assert_equal 10, s.results[0]._score
96
+
97
+ assert_equal 5, s.results[1]._score
98
+ assert_equal 5, s.results[2]._score
99
+ assert_equal 3, s.results[3]._score
100
+ assert_equal 3, s.results[4]._score
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -39,6 +39,38 @@ module Tire
39
39
  assert_equal 1, s.results.count
40
40
  end
41
41
 
42
+ context "when passing the wrapper option" do
43
+ class ::MyCustomWrapper < Tire::Results::Item
44
+ def title_size
45
+ self.title.size
46
+ end
47
+ end
48
+
49
+ should "be allowed when passing a block" do
50
+ s = Tire.search 'articles-test', wrapper: ::MyCustomWrapper do
51
+ query { match :title, 'one' }
52
+ end
53
+
54
+ assert_equal ::MyCustomWrapper, s.options[:wrapper]
55
+
56
+ assert_instance_of ::MyCustomWrapper, s.results.first
57
+ assert_equal 3, s.results.first.title_size
58
+ end
59
+
60
+ should "be allowed when not passing a block" do
61
+ s = Tire.search(
62
+ 'articles-test',
63
+ payload: { query: { match: { title: 'one' } } },
64
+ wrapper: ::MyCustomWrapper
65
+ )
66
+
67
+ assert_equal ::MyCustomWrapper, s.options[:wrapper]
68
+
69
+ assert_instance_of ::MyCustomWrapper, s.results.first
70
+ assert_equal 3, s.results.first.title_size
71
+ end
72
+ end
73
+
42
74
  end
43
75
 
44
76
  end
@@ -194,6 +194,53 @@ module Tire
194
194
 
195
195
  end
196
196
 
197
+ context "geo distance" do
198
+ setup do
199
+ @index = Tire.index('bars-test') do
200
+ delete
201
+ create :mappings => {
202
+ :bar => {
203
+ :properties => {
204
+ :name => { :type => 'string' },
205
+ :location => { :type => 'geo_point', :lat_lon => true }
206
+ }
207
+ }
208
+ }
209
+
210
+ store :type => 'bar',
211
+ :name => 'one',
212
+ :location => {:lat => 53.54412, :lon => 9.94021}
213
+ store :type => 'bar',
214
+ :name => 'two',
215
+ :location => {:lat => 53.54421, :lon => 9.94673}
216
+ store :type => 'bar',
217
+ :name => 'three',
218
+ :location => {:lat => 53.55099, :lon => 10.02527}
219
+ refresh
220
+ end
221
+ end
222
+
223
+ teardown { @index.delete }
224
+
225
+ should "return aggregated values for all results" do
226
+ s = Tire.search('bars-test') do
227
+ query { all }
228
+ facet 'geo' do
229
+ geo_distance :location,
230
+ {:lat => 53.54507, :lon => 9.95309},
231
+ [{:to => 1}, {:from => 1, :to => 10}, {:from => 50}],
232
+ unit: 'km'
233
+ end
234
+ end
235
+
236
+ facets = s.results.facets['geo']['ranges']
237
+ assert_equal 3, facets.size, facets.inspect
238
+ assert_equal 2, facets.entries[0]['total_count'], facets.inspect
239
+ assert_equal 1, facets.entries[1]['total_count'], facets.inspect
240
+ assert_equal 0, facets.entries[2]['total_count'], facets.inspect
241
+ end
242
+ end
243
+
197
244
  context "statistical" do
198
245
 
199
246
  should "return computed statistical data on a numeric field" do
@@ -10,13 +10,18 @@ module Tire
10
10
  should "allow easy access to returned documents" do
11
11
  q = 'title:one'
12
12
  s = Tire.search('articles-test') { query { string q } }
13
+
13
14
  assert_equal 'One', s.results.first.title
14
15
  assert_equal 'ruby', s.results.first.tags[0]
15
16
  end
16
17
 
17
18
  should "allow easy access to returned documents with limited fields" do
18
19
  q = 'title:one'
19
- s = Tire.search('articles-test') { query { string q }.fields :title }
20
+ s = Tire.search('articles-test') do
21
+ query { string q }
22
+ fields :title
23
+ end
24
+
20
25
  assert_equal 'One', s.results.first.title
21
26
  assert_nil s.results.first.tags
22
27
  end
@@ -27,11 +32,36 @@ module Tire
27
32
  query { string q }
28
33
  fields 'title', 'tags'
29
34
  end
35
+
30
36
  assert_equal 'One', s.results.first.title
31
37
  assert_equal 'ruby', s.results.first.tags[0]
32
38
  assert_nil s.results.first.published_on
33
39
  end
34
40
 
41
+ should "return script fields" do
42
+ s = Tire.search('articles-test') do
43
+ query { string 'title:one' }
44
+ fields :title
45
+ script_field :words_double, :script => "doc.words.value * 2"
46
+ end
47
+
48
+ assert_equal 'One', s.results.first.title
49
+ assert_equal 250, s.results.first.words_double
50
+ end
51
+
52
+ should "return specific fields, script fields and _source fields" do
53
+ # Tire.configure { logger STDERR, level: 'debug' }
54
+
55
+ s = Tire.search('articles-test') do
56
+ query { string 'title:one' }
57
+ fields :title, :_source
58
+ script_field :words_double, :script => "doc.words.value * 2"
59
+ end
60
+
61
+ assert_equal 'One', s.results.first.title
62
+ assert_equal 250, s.results.first.words_double
63
+ end
64
+
35
65
  should "iterate results with hits" do
36
66
  s = Tire.search('articles-test') { query { string 'title:one' } }
37
67
 
@@ -43,6 +43,10 @@ module Tire
43
43
  end
44
44
  end
45
45
 
46
+ should "have __host_unreachable_exceptions" do
47
+ assert_respond_to Client::RestClient, :__host_unreachable_exceptions
48
+ end
49
+
46
50
  end
47
51
 
48
52
  if defined?(Curl)
@@ -81,6 +85,10 @@ module Tire
81
85
  threads.each { |t| t.join() }
82
86
  end
83
87
 
88
+ should "have __host_unreachable_exceptions" do
89
+ assert_respond_to Client::RestClient, :__host_unreachable_exceptions
90
+ end
91
+
84
92
  end
85
93
 
86
94
  end
@@ -335,6 +335,16 @@ module Tire
335
335
  @index.store({:title => 'Test'}, {:replication => 'async'})
336
336
  end
337
337
 
338
+ should "extract the version from options" do
339
+ Configuration.client.expects(:post).
340
+ with do |url, payload|
341
+ assert_equal "#{Configuration.url}/dummy/document/?version=123", url
342
+ end.
343
+ returns(mock_response('{"ok":true,"_id":"test"}'))
344
+
345
+ @index.store({:title => 'Test'}, {:version => 123})
346
+ end
347
+
338
348
  context "document with ID" do
339
349
 
340
350
  should "store a Hash under its ID property" do
@@ -671,26 +681,44 @@ module Tire
671
681
  @index.bulk :delete, [ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ]
672
682
  end
673
683
 
674
- should "serialize meta parameters such as routing into payload header" do
684
+ should "serialize meta parameters into payload header" do
675
685
  Configuration.client.
676
686
  expects(:post).
677
687
  with do |url, payload|
678
688
  # print payload
679
689
  lines = payload.split("\n")
680
- assert_match /"_routing":"A"/, lines[0]
681
- assert_match /"_routing":"B"/, lines[2]
682
- assert_match /"_ttl":"1d"/, lines[2]
683
- assert ! lines[4].include?('"_routing"')
690
+
691
+ assert_match /"_routing":"A"/, lines[0]
692
+
693
+ assert_match /"_ttl":"1d"/, lines[2]
694
+ assert ! lines[2].include?('"_:parent"')
695
+
696
+ assert_match /"_version":"1234"/, lines[4]
697
+ assert ! lines[4].include?('"_:routing"')
698
+
699
+ assert_match /"_version_type":"external"/, lines[6]
700
+ assert ! lines[6].include?('"_:garbage"')
701
+
702
+ assert_match /"_percolate":"color:green"/, lines[8]
703
+
704
+ assert_match /"_parent":"5678"/, lines[10]
705
+
706
+ assert_match /"_timestamp":"2013-02-15 11:00:33"/, lines[12]
707
+
708
+ true
684
709
  end.
685
710
  returns(mock_response('{}'), 200)
686
711
 
687
712
  @index.bulk :index,
688
713
  [
689
- {:id => '1', :title => 'One', :_routing => 'A'},
690
- {:id => '2', :title => 'Two', :_routing => 'B', :_ttl => '1d'},
691
- {:id => '3', :title => 'Three'}
714
+ {:id => '1', :title => 'One', :_routing => 'A'},
715
+ {:id => '2', :title => 'Two', :_ttl => '1d', :_parent => false},
716
+ {:id => '3', :title => 'Three', :_version => '1234', :_routing => ""},
717
+ {:id => '4', :title => 'Four', :_version_type => 'external', :_garbage => "stuff"},
718
+ {:id => '5', :title => 'Five', :_percolate => 'color:green'},
719
+ {:id => '6', :title => 'Six', :_parent => '5678'},
720
+ {:id => '7', :title => 'Seven', :_timestamp => '2013-02-15 11:00:33'},
692
721
  ]
693
-
694
722
  end
695
723
 
696
724
  should "pass URL parameters such as refresh or consistency" do