jruby_streaming_update_solr_server 0.3.1 → 0.4.1

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.
data/README.rdoc CHANGED
@@ -25,7 +25,6 @@ See the class files for more information, documentation, and examples.
25
25
  #
26
26
  # doc = SolrInputDocument.new
27
27
  # doc.add 'title', 'This is the title'
28
- # doc.add :title, 'Another title' # symbols are automatically cast to strings for field name
29
28
  # doc << ['title', "This is yet another title, added with '<<'"]
30
29
  # doc.add 'id', 1
31
30
  # doc.add 'author', ['Mike', 'Bill', 'Molly'] # adds multiple values at once
@@ -38,8 +37,7 @@ See the class files for more information, documentation, and examples.
38
37
  # suss = StreamingUpdateSolrServer.new(url,queuesize,threads)
39
38
  # hash = {}
40
39
  # hash['title'] = This is the title'
41
- # hash[:id] = 1 # Can also take symbols instead of strings if you like
42
- # hash[:author] = ['Bill', 'Mike'] # Note that we can add multiple values at once
40
+ # hash['author'] = ['Bill', 'Mike'] # Note that we can add multiple values at once
43
41
  # suss << hash
44
42
  # # repeat as desired
45
43
  # suss.commit
@@ -56,20 +54,24 @@ construct Solr documents and send them to Solr all from within the comfort of th
56
54
 
57
55
  Note that you can use threach to multi-thread it all.
58
56
 
59
- == WARNING: Program hangs on for 60 seconds!
60
-
61
- *WARNING*: After your program ends, the StreamingUpdateSolrServer object hangs on for a full minute, presumably
62
- the timeout of the underlying http client object. I haven't figure out how to change this yet.
63
57
 
64
58
  == ToDo
65
59
 
66
60
  * Figure out why the http client hangs on for so long
67
- * Modify SolrInputDocument.add to take a relevancy weight.
68
61
  * More complete examples
69
62
 
70
63
 
71
64
  === CHANGES
72
65
 
66
+ 0.4.1 (2010.09.07)
67
+ * Updated documentation
68
+ * Added access to document-level boost via #boost and #boost=
69
+ * Added access to field-level boost via #fieldBoost and #setFieldBoost
70
+ * Added third parameter to `#add` for field-level boost
71
+ * Added #values
72
+ * Release new gem
73
+
74
+
73
75
  2010.07.09 Added #useJavabin!
74
76
 
75
77
  == Copyright
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ begin
10
10
  gem.email = "bill@dueber.com"
11
11
  gem.homepage = "http://github.com/billdueber/jruby_streaming_update_solr_server"
12
12
  gem.authors = ["Bill Dueber"]
13
- gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
13
+ gem.add_development_dependency 'bacon', ">=0"
14
14
  gem.add_development_dependency "yard", ">= 0"
15
15
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
16
  end
@@ -20,18 +20,18 @@ rescue LoadError
20
20
  end
21
21
 
22
22
  require 'rake/testtask'
23
- Rake::TestTask.new(:test) do |test|
24
- test.libs << 'lib' << 'test'
25
- test.pattern = 'test/**/test_*.rb'
26
- test.verbose = true
23
+ Rake::TestTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.pattern = 'spec/**/*_spec.rb'
26
+ spec.verbose = true
27
27
  end
28
28
 
29
29
  begin
30
30
  require 'rcov/rcovtask'
31
- Rcov::RcovTask.new do |test|
32
- test.libs << 'test'
33
- test.pattern = 'test/**/test_*.rb'
34
- test.verbose = true
31
+ Rcov::RcovTask.new do |spec|
32
+ spec.libs << 'spec'
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.verbose = true
35
35
  end
36
36
  rescue LoadError
37
37
  task :rcov do
@@ -41,7 +41,7 @@ end
41
41
 
42
42
  task :test => :check_dependencies
43
43
 
44
- task :default => :test
44
+ task :default => :spec
45
45
 
46
46
  begin
47
47
  require 'yard'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.1
@@ -67,7 +67,7 @@ class StreamingUpdateSolrServer
67
67
  # Add a document to the SUSS
68
68
  # @param [SolrInputDocument, #each_pair] doc The SolrInputDocument or hash (or hash-like object
69
69
  # that responds to #each_pair) to add. The latter must be of the form solrfield => value or
70
- # solrfield => [list, of, values]. They keys can be either symbols or strings.
70
+ # solrfield => [list, of, values]. They keys must be strings.
71
71
  #
72
72
  # @example Create and add a SolrInputDocument
73
73
  # url = 'http://solrmachine:port/solr' # URL to solr
@@ -88,8 +88,7 @@ class StreamingUpdateSolrServer
88
88
  # suss = StreamingUpdateSolrServer.new(url,queuesize,threads)
89
89
  # doc = {}
90
90
  # doc['title'] = This is the title'
91
- # doc[:id] = 1 # Can also take symbols instead of strings if you like
92
- # doc[:author] = ['Bill', 'Mike']
91
+ # doc['author'] = ['Bill', 'Mike']
93
92
  # suss << doc
94
93
  # # repeat as desired
95
94
  # suss.commit
@@ -116,18 +115,62 @@ end
116
115
  #
117
116
  # @author Bill Dueber
118
117
 
118
+ # SolrInputDocument is a wrapper around the {http://lucene.apache.org/solr/api/org/apache/solr/common/SolrInputDocument.html Java SolrInputDocument}.
119
+ # In addition to the methods below, you can call the java methods directly. Common ones are:
120
+ # * `#clear` to empty the document
121
+ # * `#size` to get the number of k-v pairs
122
+ # * `#boost` and `#boost=` to get and set the document-level boost
123
+
119
124
  class SolrInputDocument
125
+
126
+
127
+ # Get the document boost for this document
128
+ # @return [Float] the current document boost
129
+ alias_method :boost, :getDocumentBoost
130
+
131
+ # Set the document boost
132
+ # @param [Float] boost The boost for the document
133
+ # @return [Float] the new boost
134
+
135
+ alias_method :boost=, :setDocumentBoost
136
+
137
+
138
+ # Boost a field. Does nothing if the field does not exist
139
+ # @param [String] field The name of the field
140
+ # @param [Float] boost The new boost
141
+ # @return [Float] the new boost
142
+
143
+ def setFieldBoost field, boost
144
+ f = self.get(field)
145
+ if f
146
+ f.setBoost(boost)
147
+ return boost
148
+ else
149
+ return nil
150
+ end
151
+ end
152
+
153
+ # get the field boost
154
+ # @param [String] field The field whose boost you want
155
+ # @return [Float] The boost
156
+
157
+ def fieldBoost field
158
+ f = self.get(field)
159
+ if f
160
+ return f.getBoost
161
+ else
162
+ return nil
163
+ end
164
+ end
120
165
 
121
166
  # Add a value to a field. Will add all elements of an array in turn
122
- # @param [Symbol, String] field The field to add a value or values to
167
+ # @param [String] field The field to add a value or values to
123
168
  # @param [String, Numeric, #each] val The value or array-like of values to add.
169
+ # @param [Float] boost The boost for this field
124
170
  # @return [Array<String,Numeric>] An array of the field's values after this addition
125
171
 
126
- def add(field, val)
172
+ def add(field, val, boost=nil)
127
173
  return if val == nil
128
- if field.is_a?(Symbol)
129
- field = field.to_s
130
- end
131
174
  if val.is_a? String or val.is_a? Numeric
132
175
  self.addField(field, val)
133
176
  else
@@ -137,13 +180,14 @@ class SolrInputDocument
137
180
  raise NoMethodError, "SolrInputDocument values must be a string, numeric, or an array-like (responds to #each) of same, not #{val.inspect}"
138
181
  end
139
182
  end
140
- self[field]
183
+ self.boost = boost if boost
184
+ return self[field]
141
185
  end
142
186
 
143
187
 
144
- # An alternate syntax for #add, which will usuall be preferred.
188
+ # An alternate syntax for #add.
145
189
  #
146
- # @param [Array<Symbol, String>] fv A two-element array of the form [field, value] or [field, [value1, value2, ...]]
190
+ # @param [Array<String>] fv A two-element array of Strings of the form [field, value] or [field, [value1, value2, ...]]
147
191
  # @return [Array<String>] the list of current values for the field in fv[0]
148
192
  #
149
193
  # @example Add some fields
@@ -162,13 +206,10 @@ class SolrInputDocument
162
206
  #
163
207
  # Note that this will always return either nil (not found) or an array, even of one element
164
208
  #
165
- # @param [String, Symbol] field The field whose values you want (as String or Symbol)
209
+ # @param [String] field The field whose values you want (as String)
166
210
  # @return [Array<String>] An array of values (or nil on not found)
167
211
  #
168
212
  def [] field
169
- if field.is_a?(Symbol)
170
- field = field.to_s
171
- end
172
213
  f = self.get(field)
173
214
  return nil if (f == nil)
174
215
  return f.values.to_a
@@ -178,23 +219,20 @@ class SolrInputDocument
178
219
  #
179
220
  # Note that this is destructive; see #<< to add multiple values to a field
180
221
  #
181
- # @param [String, Symbol] field The solr field you're setting the value of
222
+ # @param [String] field The solr field you're setting the value of
182
223
  # @param [String, Array<String>] value The value or array of values to set
183
224
  # @return [Array<String>] The list of values (i.e., either +value+ or +[value]+)
184
225
  #
185
226
  # @example
186
227
  # doc = SolrInputDocument.new
187
- # doc[:id] = 1 #=> [1]
188
- # doc[:author] = 'Mike' #=> ['Mike']
189
- # doc[:author] = 'Bill' #=> ['Bill']
190
- # doc[:author] #=> ['Bill']
228
+ # doc['id'] = 1 #=> [1]
229
+ # doc['author'] = 'Mike' #=> ['Mike']
230
+ # doc['author'] = 'Bill' #=> ['Bill']
231
+ # doc['author'] #=> ['Bill']
191
232
 
192
233
  def []= field, value
193
- if field.is_a?(Symbol)
194
- field = field.to_s
195
- end
196
234
  self.removeField(field)
197
- self.add(field, value)
235
+ self.add(field, value) unless value.nil?
198
236
  end
199
237
 
200
238
 
@@ -206,15 +244,15 @@ class SolrInputDocument
206
244
  #
207
245
  # @example Merge a hash into an existing document
208
246
  # doc = SolrInputDocument.new
209
- # doc << [:author, 'Bill']
247
+ # doc << ['author', 'Bill']
210
248
  # h = {}
211
249
  # h['author'] = 'Mike'
212
250
  # h['id'] = 1
213
- # h[:copies] = ['Grad reference', 'Long-term storage']
251
+ # h['copies'] = ['Grad reference', 'Long-term storage']
214
252
  # doc.merge! h
215
- # doc[:id] #=> 1
216
- # doc[:author] #=> ['Bill', 'Mike']
217
- # doc[:copies] #=> ['Grad reference', 'Long-term storage']
253
+ # doc['id'] #=> 1
254
+ # doc['author'] #=> ['Bill', 'Mike']
255
+ # doc['copies'] #=> ['Grad reference', 'Long-term storage']
218
256
 
219
257
  def merge! h
220
258
  unless h.respond_to? :each_pair
@@ -241,17 +279,45 @@ class SolrInputDocument
241
279
  return self.keySet.to_a
242
280
  end
243
281
 
282
+ # Get the values as an array
283
+ # @return [Array<String] An array of all the values in all the keys (flattened out)
284
+ #
285
+ alias_method :oldvalues, :values
286
+ def values
287
+ rv = self.keys.map {|k| self[k]}
288
+ rv.uniq!
289
+ rv.flatten!
290
+ return rv
291
+ end
292
+
244
293
  # Does this doc contain the given key?
245
- # @param [Symbol, String] field The field whose presence you want to check
294
+ # @param [String] field The field whose presence you want to check
246
295
  # @return [Boolean] True if the key is present
247
296
 
248
297
  def has_key? field
249
- if field.is_a?(Symbol)
250
- field = field.to_s
251
- end
252
298
  return self.containsKey(field)
253
299
  end
254
300
 
301
+ # Does this doc have the given value?
302
+ # @param [String] value to look for
303
+ # @return [Boolean]
304
+
305
+ def has_value? val
306
+ self.keys.each do |k|
307
+ return true if self[k].include? val
308
+ end
309
+ return false
310
+ end
311
+
312
+ # Delete a key/value pair
313
+ # @param [String] key The key
314
+ # @return [Array<String>] The removed values (or nil)
315
+
316
+ def delete key
317
+ rv = self[key]
318
+ self.removeField key
319
+ return rv
320
+ end
255
321
 
256
322
  end
257
323
 
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe "SolrDocument" do
4
+
5
+ before do
6
+ @doc = SolrInputDocument.new
7
+ end
8
+
9
+ it "starts out empty" do
10
+ @doc.empty?.should.equal true
11
+ @doc.size.should.equal 0
12
+ @doc.values.should.equal []
13
+ @doc.keys.should.equal []
14
+ end
15
+
16
+ it "reports nil for an unset field" do
17
+ @doc['notinhere'].should.equal nil
18
+ end
19
+
20
+ it "sets using =" do
21
+ @doc['t'] = 1
22
+ @doc['t'].should.equal [1]
23
+ @doc['t'] = 2
24
+ @doc['t'].should.equal [2]
25
+ end
26
+
27
+ it "adds using <<" do
28
+ @doc << ['t', 1]
29
+ @doc['t'].should.equal [1]
30
+ @doc << ['t', 2]
31
+ @doc['t'].should.equal [1,2]
32
+ end
33
+
34
+ it "adds items in hash via merge!" do
35
+ @doc << ['id', '1']
36
+ h = {'id' => '2', 'name' => 'Bill'}
37
+ @doc.merge! h
38
+ @doc['id'].should.equal ['1', '2']
39
+ @doc['name'].should.equal ['Bill']
40
+ @doc.values.sort.should.equal ['1', '2','Bill'].sort
41
+ end
42
+
43
+ it "aliases additive_merge! as well" do
44
+ @doc << ['id', 1]
45
+ h = {'id' => 2, 'name' => 'Bill'}
46
+ @doc.additive_merge! h
47
+ @doc['id'].should.equal [1,2]
48
+ @doc['name'].should.equal ['Bill']
49
+ end
50
+
51
+ it "correctly finds keys and values" do
52
+ @doc << ['id', '1']
53
+ @doc << ['name', 'Bill']
54
+ @doc.has_key?('name').should.equal true
55
+ @doc.has_key?('id').should.equal true
56
+ @doc.has_key?('junk').should.equal false
57
+ @doc.has_value?('1').should.equal true
58
+ @doc.has_value?('Bill').should.equal true
59
+ @doc.has_value?('junk').should.equal false
60
+ end
61
+
62
+ it "can add multiple items at once" do
63
+ @doc.add('name', ['Bill', 'Mike', 'Molly'])
64
+ @doc['name'].sort.should.equal ['Bill', 'Mike', 'Molly'].sort
65
+ end
66
+
67
+ it "boosts the doc" do
68
+ @doc.boost = 100
69
+ @doc.boost.should.equal 100
70
+ end
71
+
72
+ it "boosts a field" do
73
+ @doc.add('id', '1')
74
+ @doc.fieldBoost('id').should.equal 1.0
75
+ @doc.setFieldBoost('id', 100.0)
76
+ @doc.fieldBoost('id').should.equal 100.0
77
+ @doc.setFieldBoost('junk', 100.0).should.equal nil
78
+ @doc.fieldBoost('junk').should.equal nil
79
+
80
+ end
81
+
82
+ end
@@ -1,10 +1,14 @@
1
1
  require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
2
+ require 'bacon'
3
+ begin
4
+ require 'greeneggs'
5
+ rescue LoadError
6
+ end
4
7
 
5
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
8
  $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
10
  require 'jruby_streaming_update_solr_server'
8
11
 
9
- class Test::Unit::TestCase
10
- end
12
+ DIR = File.dirname(__FILE__)
13
+
14
+ Bacon.summary_on_exit
metadata CHANGED
@@ -1,46 +1,51 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jruby_streaming_update_solr_server
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 13
4
5
  prerelease: false
5
6
  segments:
6
- - 0
7
- - 3
8
- - 1
9
- version: 0.3.1
7
+ - 0
8
+ - 4
9
+ - 1
10
+ version: 0.4.1
10
11
  platform: ruby
11
12
  authors:
12
- - Bill Dueber
13
+ - Bill Dueber
13
14
  autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-08-16 00:00:00 -04:00
18
+ date: 2010-09-07 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: thoughtbot-shoulda
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- version: "0"
30
- type: :development
31
- version_requirements: *id001
32
- - !ruby/object:Gem::Dependency
33
- name: yard
34
- prerelease: false
35
- requirement: &id002 !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- segments:
40
- - 0
41
- version: "0"
42
- type: :development
43
- version_requirements: *id002
21
+ - !ruby/object:Gem::Dependency
22
+ name: bacon
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: yard
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
44
49
  description: Some sugar on top of StreamingUpdateSolrServer for use within JRuby
45
50
  email: bill@dueber.com
46
51
  executables: []
@@ -48,52 +53,56 @@ executables: []
48
53
  extensions: []
49
54
 
50
55
  extra_rdoc_files:
51
- - LICENSE
52
- - README.rdoc
56
+ - LICENSE
57
+ - README.rdoc
53
58
  files:
54
- - LICENSE
55
- - README.rdoc
56
- - Rakefile
57
- - VERSION
58
- - jars/apache-solr-solrj-1.5-dev.jar
59
- - jars/commons-codec-1.3.jar
60
- - jars/commons-httpclient-3.1.jar
61
- - jars/commons-logging-1.1.1.jar
62
- - jars/slf4j-api-1.5.5.jar
63
- - jars/slf4j-jdk14-1.5.5 2.jar
64
- - lib/jruby_streaming_update_solr_server.rb
65
- - test/helper.rb
66
- - test/test_jruby_streaming_update_solr_server.rb
59
+ - LICENSE
60
+ - README.rdoc
61
+ - Rakefile
62
+ - VERSION
63
+ - jars/apache-solr-solrj-1.5-dev.jar
64
+ - jars/commons-codec-1.3.jar
65
+ - jars/commons-httpclient-3.1.jar
66
+ - jars/commons-logging-1.1.1.jar
67
+ - jars/slf4j-api-1.5.5.jar
68
+ - jars/slf4j-jdk14-1.5.5 2.jar
69
+ - lib/jruby_streaming_update_solr_server.rb
70
+ - spec/basics_spec.rb
71
+ - spec/spec_helper.rb
67
72
  has_rdoc: true
68
73
  homepage: http://github.com/billdueber/jruby_streaming_update_solr_server
69
74
  licenses: []
70
75
 
71
76
  post_install_message:
72
77
  rdoc_options:
73
- - --charset=UTF-8
78
+ - --charset=UTF-8
74
79
  require_paths:
75
- - lib
80
+ - lib
76
81
  required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
77
83
  requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- segments:
81
- - 0
82
- version: "0"
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
83
90
  required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
84
92
  requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- segments:
88
- - 0
89
- version: "0"
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
90
99
  requirements: []
91
100
 
92
101
  rubyforge_project:
93
- rubygems_version: 1.3.6
102
+ rubygems_version: 1.3.7
94
103
  signing_key:
95
104
  specification_version: 3
96
105
  summary: Simple jruby interface into StreamingUpdateSolrServer
97
106
  test_files:
98
- - test/helper.rb
99
- - test/test_jruby_streaming_update_solr_server.rb
107
+ - spec/basics_spec.rb
108
+ - spec/spec_helper.rb
@@ -1,49 +0,0 @@
1
- require 'helper'
2
-
3
- class TestJrubyStreamingUpdateSolrServer < Test::Unit::TestCase
4
- should "Write some tests, but don't know how to mock up a solr server" do
5
- assert_equal 1, 1
6
- end
7
-
8
- should "Report nil for a document that doesn't include a field" do
9
- doc = SolrInputDocument.new
10
- assert_equal nil, doc[:notinthere]
11
- end
12
-
13
- should "Return single and multiple values in arrays" do
14
- doc = SolrInputDocument.new
15
- doc << [:id, 1]
16
- assert_equal [1], doc[:id]
17
- doc << [:id, 2]
18
- assert_equal [1,2], doc[:id]
19
- end
20
-
21
- should "Add items in hash via merge!" do
22
- doc = SolrInputDocument.new
23
- doc << [:id, 1]
24
- h = {:id => 2, :name => 'Bill'}
25
- doc.merge! h
26
- assert_equal [1,2], doc[:id]
27
- assert_equal ['Bill'], doc[:name]
28
- end
29
-
30
- should "Allow additive_merge! as well" do
31
- doc = SolrInputDocument.new
32
- doc << [:id, 1]
33
- h = {:id => 2, :name => 'Bill'}
34
- doc.additive_merge! h
35
- assert_equal [1,2], doc[:id]
36
- assert_equal ['Bill'], doc[:name]
37
-
38
- end
39
-
40
- should "Destroy existing items via []=" do
41
- doc = SolrInputDocument.new
42
- doc[:id] = 1
43
- assert_equal [1], doc[:id]
44
- doc[:id] = 2
45
- assert_equal [2], doc[:id]
46
- end
47
-
48
-
49
- end