delsolr 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,7 +59,7 @@ module DelSolr
59
59
  # remove params as we go so we can just pass whatever is left to solr...
60
60
 
61
61
  params << build_query(:q, opts.delete(:q))
62
- params << {:wt => 'ruby'}
62
+ params << {:wt => 'json'}
63
63
  params << {:qt => query_name}
64
64
  params << {:rows => opts.delete(:rows)}
65
65
  params << {:start => opts.delete(:start)}
@@ -1,7 +1,5 @@
1
1
  module DelSolr
2
-
3
2
  class Client
4
-
5
3
  class Response
6
4
 
7
5
  attr_reader :query_builder
@@ -11,11 +9,13 @@ module DelSolr
11
9
  @from_cache = options[:from_cache]
12
10
  @logger = options[:logger]
13
11
  begin
14
- @raw_response = eval(solr_response_buffer)
15
- rescue SyntaxError, Exception => e
16
- @logger.error(solr_response_buffer) if @logger
17
- @logger.error(e) if @logger
18
- @raw_response = nil
12
+ @raw_response = JSON.parse(solr_response_buffer)
13
+ rescue JSON::ParserError => e
14
+ if @logger
15
+ @logger.error(solr_response_buffer)
16
+ @logger.error(e.message)
17
+ end
18
+ raise e
19
19
  end
20
20
 
21
21
  # now define the shortcuts
@@ -1,13 +1,13 @@
1
1
  module DelSolr
2
2
  #
3
3
  # DelSolr::Client::Document
4
- #
4
+ #
5
5
  # Generally, indexing consists of iterating over your database, creating a huge xml buffer, and
6
6
  # posting it to solr. This wraps up the xml portion and DelSolr::Client wraps up the posting/batching
7
7
  # portions.
8
- #
8
+ #
9
9
  # This is what your indexing logic might look like if you're dealing w/ ActiveRecord objects:
10
- #
10
+ #
11
11
  # client = DelSolr::Client.new(:server => 'solr1', :port => 8983, :timout => 500)
12
12
  # models = SomeModel.find(:all)
13
13
  # models.each do |model|
@@ -21,19 +21,19 @@ module DelSolr
21
21
  # end
22
22
  # client.post_update! # send the batch to solr
23
23
  # client.commit! # send the commit so solr updates the index
24
- #
24
+ #
25
25
  # It's generally a good idea to experiment with different batch size. 500-2000 documents per post
26
26
  # is a good starting point depending on how large your documents are.
27
- #
27
+ #
28
28
  # You also may want to just update a signle document when it is changed. Might looks like this:
29
- #
29
+ #
30
30
  # def after_save
31
31
  # doc = DelSolr::Document.new
32
32
  # doc.add_field('id', model.id)
33
33
  # doc.add_field('name', model.name)
34
34
  # $client.update_and_commit!(doc) # post the document and immediately post the commit
35
35
  # end
36
- #
36
+ #
37
37
  #
38
38
  class Document
39
39
 
@@ -47,14 +47,14 @@ module DelSolr
47
47
  # is the value of the field you wish to be indexed
48
48
  # [<b><tt>options</tt></b>]
49
49
  # <b><tt>:cdata</tt></b> set to true if you want the value wrap in a CDATA tag
50
- #
50
+ #
51
51
  # All other options are passed directly as xml attributes (see the solr documentation on usage)
52
52
  def add_field(field_name, value, options = {})
53
53
  field_buffer << construct_field_tag(field_name, value, options)
54
54
  end
55
55
 
56
56
  def xml
57
- "<doc#{opts2str(@options)}>\n" + field_buffer + "</doc>"
57
+ "<doc#{@options.to_xml_attribute_string}>\n" + field_buffer + "</doc>"
58
58
  end
59
59
 
60
60
  private
@@ -64,8 +64,8 @@ module DelSolr
64
64
  options[:name] = name.to_s
65
65
  use_cdata = options.delete(:cdata)
66
66
 
67
- return "<field#{opts2str(options)}>#{use_cdata ? cdata(value) : value}</field>\n"
68
- end
67
+ return "<field#{options.to_xml_attribute_string}>#{use_cdata ? cdata(value) : value}</field>\n"
68
+ end
69
69
 
70
70
  def cdata(str)
71
71
  "<![CDATA[#{str}]]>"
@@ -75,16 +75,6 @@ module DelSolr
75
75
  @buffer ||= ""
76
76
  end
77
77
 
78
- def opts2str(options)
79
- opts = []
80
- options.each do |k,v|
81
- opts.push "#{k}=\"#{v}\""
82
- end
83
- opts = opts.join(" ")
84
- opts = " " + opts unless opts.blank?
85
- opts
86
- end
87
-
88
78
  end
89
-
79
+
90
80
  end
@@ -3,7 +3,7 @@
3
3
  #
4
4
 
5
5
  String.class_eval do
6
- if !''.respond_to?(:blank?)
6
+ if !''.respond_to?(:blank?)
7
7
  def blank?
8
8
  self == ''
9
9
  end
@@ -32,4 +32,18 @@ Fixnum.class_eval do
32
32
  self * 60 * 60
33
33
  end
34
34
  end
35
+ end
36
+
37
+ class Hash
38
+
39
+ def to_xml_attribute_string
40
+ opts = []
41
+ self.each do |k,v|
42
+ opts.push "#{k}=\"#{v}\""
43
+ end
44
+ opts = opts.join(" ")
45
+ opts = " " + opts unless opts.blank?
46
+ opts
47
+ end
48
+
35
49
  end
metadata CHANGED
@@ -1,27 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delsolr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ben VandenBos
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2009-11-02 00:00:00.000000000Z
11
+ date: 2009-11-02 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.8.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.8.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
14
41
  - !ruby/object:Gem::Dependency
15
42
  name: mocha
16
- requirement: &2171652600 !ruby/object:Gem::Requirement
17
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
18
44
  requirements:
19
- - - ! '>='
45
+ - - ">="
20
46
  - !ruby/object:Gem::Version
21
47
  version: 0.9.0
22
48
  type: :development
23
49
  prerelease: false
24
- version_requirements: *2171652600
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.2
25
69
  description: Ruby wrapper for Lucene Solr
26
70
  email:
27
71
  executables: []
@@ -29,44 +73,38 @@ extensions: []
29
73
  extra_rdoc_files: []
30
74
  files:
31
75
  - License.txt
32
- - README.txt
76
+ - README.rdoc
77
+ - Rakefile
33
78
  - lib/delsolr.rb
34
- - lib/delsolr/configuration.rb
35
- - lib/delsolr/extensions.rb
36
- - lib/delsolr/query_builder.rb
37
- - lib/delsolr/response.rb
79
+ - lib/delsolr/client.rb
80
+ - lib/delsolr/client/configuration.rb
81
+ - lib/delsolr/client/query_builder.rb
82
+ - lib/delsolr/client/response.rb
38
83
  - lib/delsolr/document.rb
39
- - test/test_client.rb
40
- - test/test_helper.rb
41
- - test/test_query_builder.rb
42
- - test/test_response.rb
84
+ - lib/delsolr/extensions.rb
43
85
  homepage: http://github.com/avvo/delsolr
44
86
  licenses: []
87
+ metadata: {}
45
88
  post_install_message:
46
89
  rdoc_options: []
47
90
  require_paths:
48
91
  - lib
49
92
  required_ruby_version: !ruby/object:Gem::Requirement
50
- none: false
51
93
  requirements:
52
- - - ! '>='
94
+ - - ">="
53
95
  - !ruby/object:Gem::Version
54
96
  version: '0'
55
97
  required_rubygems_version: !ruby/object:Gem::Requirement
56
- none: false
57
98
  requirements:
58
- - - ! '>='
99
+ - - ">="
59
100
  - !ruby/object:Gem::Version
60
101
  version: '0'
61
102
  requirements: []
62
103
  rubyforge_project:
63
- rubygems_version: 1.8.5
104
+ rubygems_version: 2.2.0.rc.1
64
105
  signing_key:
65
- specification_version: 3
106
+ specification_version: 4
66
107
  summary: DelSolr is a light weight ruby wrapper for solr. It's intention is to expose
67
108
  the full power of solr queries while keeping the interface as ruby-esque as possible.
68
- test_files:
69
- - test/test_client.rb
70
- - test/test_helper.rb
71
- - test/test_query_builder.rb
72
- - test/test_response.rb
109
+ test_files: []
110
+ has_rdoc:
@@ -1,268 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
- require 'rubygems'
3
- gem 'mocha', '>=0.9.0'
4
- require 'mocha'
5
-
6
- class ClientTest < Test::Unit::TestCase
7
-
8
- include Test::Unit::Assertions
9
-
10
- SUCCESS = '<result status="0"></result>'
11
- FAILURE = '<result status="1"></result>'
12
- CONTENT_TYPE = {'Content-type' => 'text/xml;charset=utf-8'}
13
-
14
- class TestCache
15
- def set(k,v,t)
16
- @cache ||= {}
17
- @cache[k] = v
18
- end
19
-
20
- def get(k)
21
- @cache ||= {}
22
- @cache[k]
23
- end
24
- end
25
-
26
- @@response_buffer = %{
27
- {
28
- 'responseHeader'=>{
29
- 'status'=>0,
30
- 'QTime'=>151,
31
- 'params'=>{
32
- 'wt'=>'ruby',
33
- 'rows'=>'10',
34
- 'explainOther'=>'',
35
- 'start'=>'0',
36
- 'hl.fl'=>'',
37
- 'indent'=>'on',
38
- 'hl'=>'on',
39
- 'q'=>'index_type:widget',
40
- 'fl'=>'*,score',
41
- 'qt'=>'standard',
42
- 'version'=>'2.2'}},
43
- 'response'=>{'numFound'=>1522698,'start'=>0,'maxScore'=>1.5583541,'docs'=>[
44
- {
45
- 'index_type'=>'widget',
46
- 'id'=>1,
47
- 'unique_id'=>'1_widget',
48
- 'score'=>1.5583541},
49
- {
50
- 'index_type'=>'widget',
51
- 'id'=>3,
52
- 'unique_id'=>'3_widget',
53
- 'score'=>1.5583541},
54
- {
55
- 'index_type'=>'widget',
56
- 'id'=>4,
57
- 'unique_id'=>'4_widget',
58
- 'score'=>1.5583541},
59
- {
60
- 'index_type'=>'widget',
61
- 'id'=>5,
62
- 'unique_id'=>'5_widget',
63
- 'score'=>1.5583541},
64
- {
65
- 'index_type'=>'widget',
66
- 'id'=>7,
67
- 'unique_id'=>'7_widget',
68
- 'score'=>1.5583541},
69
- {
70
- 'index_type'=>'widget',
71
- 'id'=>8,
72
- 'unique_id'=>'8_widget',
73
- 'score'=>1.5583541},
74
- {
75
- 'index_type'=>'widget',
76
- 'id'=>9,
77
- 'unique_id'=>'9_widget',
78
- 'score'=>1.5583541},
79
- {
80
- 'index_type'=>'widget',
81
- 'id'=>10,
82
- 'unique_id'=>'10_widget',
83
- 'score'=>1.5583541},
84
- {
85
- 'index_type'=>'widget',
86
- 'id'=>11,
87
- 'unique_id'=>'11_widget',
88
- 'score'=>1.5583541},
89
- {
90
- 'index_type'=>'widget',
91
- 'id'=>12,
92
- 'unique_id'=>'12_widget',
93
- 'score'=>1.5583541}]
94
- },
95
- 'facet_counts'=>{
96
- 'facet_queries'=>{
97
- 'city_idm:19596' => 392},
98
- 'facet_fields'=>{
99
- 'available_b'=>[
100
- 'false',1328],
101
- 'onsale_b'=>[
102
- 'false',1182,
103
- 'true',174]}},
104
- 'highlighting'=>{
105
- '1_widget'=>{},
106
- '3_widget'=>{},
107
- '4_widget'=>{},
108
- '5_widget'=>{},
109
- '7_widget'=>{},
110
- '8_widget'=>{},
111
- '9_widget'=>{},
112
- '10_widget'=>{},
113
- '11_widget'=>{},
114
- '12_widget'=>{}}}
115
- }
116
-
117
- def test_create
118
- s = nil
119
- assert_nothing_raised do
120
- s = DelSolr::Client.new(:server => 'localhost', :port => 8983)
121
- end
122
- assert(s)
123
- end
124
-
125
- def test_commit_success
126
- c = setup_client
127
- c.connection.expects(:post).once.returns([nil,SUCCESS])
128
- assert(c.commit!)
129
- end
130
-
131
- def test_commit_failure
132
- c = setup_client
133
- c.connection.expects(:post).once.returns([nil,FAILURE])
134
- assert(!c.commit!)
135
- end
136
-
137
- def test_optimize_success
138
- c = setup_client
139
- c.connection.expects(:post).once.returns([nil,SUCCESS])
140
- assert(c.optimize!)
141
- end
142
-
143
- def test_optimize_failure
144
- c = setup_client
145
- c.connection.expects(:post).once.returns([nil,FAILURE])
146
- assert(!c.optimize!)
147
- end
148
-
149
- def test_update
150
- c = setup_client
151
-
152
- doc = DelSolr::Document.new
153
- doc.add_field(:id, 123)
154
- doc.add_field(:name, 'mp3 player')
155
-
156
- expected_post_data = "<add>\n#{doc.xml}\n</add>\n"
157
-
158
- assert(c.update(doc))
159
- assert_equal(1, c.pending_documents.length)
160
-
161
- c.connection.expects(:post).with('/solr/update', expected_post_data, CONTENT_TYPE).returns([nil,SUCCESS])
162
- assert(c.post_update!)
163
- assert_equal(0, c.pending_documents.length)
164
- end
165
-
166
- def test_update!
167
- c = setup_client
168
-
169
- doc = DelSolr::Document.new
170
- doc.add_field(:id, 123)
171
- doc.add_field(:name, 'mp3 player')
172
-
173
- expected_post_data = "<add>\n#{doc.xml}\n</add>\n"
174
-
175
- c.connection.expects(:post).with('/solr/update', expected_post_data, CONTENT_TYPE).returns([nil,SUCCESS])
176
- assert(c.update!(doc))
177
- assert_equal(0, c.pending_documents.length)
178
- end
179
-
180
- def test_query_returns_nil_when_exception_thrown
181
- c = setup_client
182
-
183
- mock_query_builder = DelSolr::Client::QueryBuilder
184
- mock_query_builder.stubs(:request_string).returns('/select?some_query') # mock the query builder
185
- DelSolr::Client::QueryBuilder.stubs(:new).returns(mock_query_builder)
186
- c.connection.expects(:post).raises(StandardError) # mock the connection
187
- assert_nothing_raised do
188
- r = c.query('standard', :query => '123')
189
- assert_nil(r)
190
- end
191
- end
192
-
193
- def test_query_with_path
194
- c = setup_client(:path => '/abcsolr')
195
-
196
- mock_query_builder = DelSolr::Client::QueryBuilder
197
- mock_query_builder.stubs(:request_string).returns('/select?some_query') # mock the query builder
198
- DelSolr::Client::QueryBuilder.stubs(:new).returns(mock_query_builder)
199
- c.connection.expects(:post).with("/abcsolr/select", mock_query_builder.request_string).returns([nil, @@response_buffer]) # mock the connection
200
- r = c.query('standard', :query => '123')
201
- assert(r)
202
- assert_equal([1,3,4,5,7,8,9,10,11,12], r.ids.sort)
203
- assert(!r.from_cache?, 'should not be from cache')
204
- end
205
-
206
- def test_query_with_default_path
207
- c = setup_client
208
-
209
- mock_query_builder = DelSolr::Client::QueryBuilder
210
- mock_query_builder.stubs(:request_string).returns('/select?some_query') # mock the query builder
211
- DelSolr::Client::QueryBuilder.stubs(:new).returns(mock_query_builder)
212
- c.connection.expects(:post).with("/solr/select", mock_query_builder.request_string).returns([nil, @@response_buffer]) # mock the connection
213
- r = c.query('standard', :query => '123')
214
- assert(r)
215
- assert_equal([1,3,4,5,7,8,9,10,11,12], r.ids.sort)
216
- assert(!r.from_cache?, 'should not be from cache')
217
- end
218
-
219
-
220
- def test_query_from_cache
221
- c = setup_client(:cache => TestCache.new)
222
-
223
- mock_query_builder = DelSolr::Client::QueryBuilder
224
- mock_query_builder.stubs(:request_string).returns('/select?some_query') # mock the query builder
225
- DelSolr::Client::QueryBuilder.stubs(:new).returns(mock_query_builder)
226
- c.connection.expects(:post).with("/solr/select", mock_query_builder.request_string).returns([nil, @@response_buffer]) # mock the connection
227
- r = c.query('standard', :query => '123', :enable_caching => true)
228
- assert(r)
229
- assert_equal([1,3,4,5,7,8,9,10,11,12], r.ids.sort)
230
- assert(!r.from_cache?, 'should not be from cache')
231
-
232
- r = c.query('standard', :query => '123', :enable_caching => true)
233
- assert(r)
234
- assert_equal([1,3,4,5,7,8,9,10,11,12], r.ids.sort)
235
- assert(r.from_cache?, 'this one should be from the cache')
236
- end
237
-
238
- if RUBY_VERSION.to_f >= 1.9
239
- def test_query_encoding_ruby19_ut8
240
- c = setup_client
241
-
242
- mock_query_builder = DelSolr::Client::QueryBuilder
243
- mock_query_builder.stubs(:request_string).returns('/select?some_query') # mock the query builder
244
- DelSolr::Client::QueryBuilder.stubs(:new).returns(mock_query_builder)
245
- c.connection.expects(:post).with("/solr/select", mock_query_builder.request_string).returns([nil, @@response_buffer]) # mock the connection
246
- r = c.query('standard', :query => '123')
247
- assert(r)
248
-
249
- ensure_encoding = lambda { |v|
250
- case v
251
- when String; assert_equal 'UTF-8', v.encoding.name
252
- when Array; v.each(&ensure_encoding)
253
- when Hash; (v.keys + v.values).each(&ensure_encoding)
254
- end
255
- }
256
-
257
- ensure_encoding.call(r.raw_response)
258
- end
259
- end
260
-
261
-
262
- private
263
-
264
- def setup_client(options = {})
265
- DelSolr::Client.new({:server => 'localhost', :port => 8983}.merge(options))
266
- end
267
-
268
- end