mwmitchell-rsolr 0.9.0 → 0.9.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/CHANGES.txt +3 -0
- data/lib/rsolr/message/builders/builder.rb +85 -0
- data/lib/rsolr/message/builders/libxml.rb +59 -0
- data/lib/rsolr/message/builders.rb +6 -0
- data/lib/rsolr/message.rb +17 -37
- data/rsolr.gemspec +5 -2
- data/test/message_test.rb +49 -20
- metadata +5 -2
data/CHANGES.txt
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'builder'
|
|
2
|
+
|
|
3
|
+
class RSolr::Message::Builders::Builder
|
|
4
|
+
|
|
5
|
+
# shortcut method -> xml = RSolr::Message.xml
|
|
6
|
+
def xml
|
|
7
|
+
::Builder::XmlMarkup.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# generates "add" xml for updating solr
|
|
11
|
+
# "data" can be a hash or an array of hashes.
|
|
12
|
+
# - each hash should be a simple key=>value pair representing a solr doc.
|
|
13
|
+
# If a value is an array, multiple fields will be created.
|
|
14
|
+
#
|
|
15
|
+
# "add_attrs" can be a hash for setting the add xml element attributes.
|
|
16
|
+
#
|
|
17
|
+
# This method can also accept a block.
|
|
18
|
+
# The value yielded to the block is a Message::Document; for each solr doc in "data".
|
|
19
|
+
# You can set xml element attributes for each "doc" element or individual "field" elements.
|
|
20
|
+
#
|
|
21
|
+
# For example:
|
|
22
|
+
#
|
|
23
|
+
# solr.add({:id=>1, :nickname=>'Tim'}, {:boost=>5.0, :commitWithin=>1.0}) do |doc_msg|
|
|
24
|
+
# doc_msg.attrs[:boost] = 10.00 # boost the document
|
|
25
|
+
# nickname = doc_msg.field_by_name(:nickname)
|
|
26
|
+
# nickname.attrs[:boost] = 20 if nickname.value=='Tim' # boost a field
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# would result in an add element having the attributes boost="10.0"
|
|
30
|
+
# and a commitWithin="1.0".
|
|
31
|
+
# Each doc element would have a boost="10.0".
|
|
32
|
+
# The "nickname" field would have a boost="20.0"
|
|
33
|
+
# if the doc had a "nickname" field with the value of "Tim".
|
|
34
|
+
#
|
|
35
|
+
def add(documents, add_attrs={})
|
|
36
|
+
xml.add(add_attrs) do |add_node|
|
|
37
|
+
documents.each do |doc|
|
|
38
|
+
# create doc, passing in fields
|
|
39
|
+
add_node.doc(doc.attrs) do |doc_node|
|
|
40
|
+
doc.fields.each do |field_obj|
|
|
41
|
+
doc_node.field(field_obj.value, field_obj.attrs)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# generates a <commit/> message
|
|
49
|
+
def commit(opts={})
|
|
50
|
+
xml.commit(opts)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# generates a <optimize/> message
|
|
54
|
+
def optimize(opts={})
|
|
55
|
+
xml.optimize(opts)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# generates a <rollback/> message
|
|
59
|
+
def rollback
|
|
60
|
+
xml.rollback
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# generates a <delete><id>ID</id></delete> message
|
|
64
|
+
# "ids" can be a single value or array of values
|
|
65
|
+
def delete_by_id(ids)
|
|
66
|
+
ids = [ids] unless ids.is_a?(Array)
|
|
67
|
+
xml.delete do |xml|
|
|
68
|
+
ids.each do |id|
|
|
69
|
+
xml.id(id)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# generates a <delete><query>ID</query></delete> message
|
|
75
|
+
# "queries" can be a single value or an array of values
|
|
76
|
+
def delete_by_query(queries)
|
|
77
|
+
queries = [queries] unless queries.is_a?(Array)
|
|
78
|
+
xml.delete do |xml|
|
|
79
|
+
queries.each do |query|
|
|
80
|
+
xml.query(query)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'libxml'
|
|
2
|
+
|
|
3
|
+
class RSolr::Message::Builders::Libxml
|
|
4
|
+
|
|
5
|
+
def add(documents, attributes = {})
|
|
6
|
+
add_node = new_node('add', attributes)
|
|
7
|
+
for document in documents
|
|
8
|
+
add_node << doc_node = new_node('doc', document.attrs)
|
|
9
|
+
for field in document.fields
|
|
10
|
+
doc_node << field_node = new_node('field', field.attrs)
|
|
11
|
+
field_node << field.value
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
add_node.to_s(:indent => false)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def delete_by_id(ids)
|
|
18
|
+
delete = new_node('delete')
|
|
19
|
+
for id in Array(ids)
|
|
20
|
+
id_node = new_node('id')
|
|
21
|
+
id_node << id
|
|
22
|
+
delete << id_node
|
|
23
|
+
end
|
|
24
|
+
delete.to_s(:indent => false)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def delete_by_query(queries)
|
|
28
|
+
delete = new_node('delete')
|
|
29
|
+
for query in Array(queries)
|
|
30
|
+
query_node = new_node('query')
|
|
31
|
+
query_node << query
|
|
32
|
+
delete << query_node
|
|
33
|
+
end
|
|
34
|
+
delete.to_s(:indent => false)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def optimize(opts)
|
|
38
|
+
new_node('optimize', opts).to_s
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def rollback
|
|
42
|
+
new_node('rollback').to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def commit(opts = {})
|
|
46
|
+
new_node('commit', opts).to_s
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def new_node(name, opts = {})
|
|
52
|
+
node = LibXML::XML::Node.new(name)
|
|
53
|
+
opts.each_pair do |attr, value|
|
|
54
|
+
node[attr.to_s] = value.to_s
|
|
55
|
+
end
|
|
56
|
+
node
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
data/lib/rsolr/message.rb
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
# http://builder.rubyforge.org/
|
|
2
|
-
require 'rubygems'
|
|
3
|
-
require 'builder'
|
|
4
|
-
|
|
5
1
|
# The Solr::Message class is the XML generation module for sending updates to Solr.
|
|
6
2
|
|
|
7
3
|
class RSolr::Message
|
|
8
4
|
|
|
5
|
+
autoload :Builders, 'rsolr/message/builders'
|
|
6
|
+
|
|
9
7
|
# A class that represents a "doc" xml element for a solr update
|
|
10
8
|
class Document
|
|
11
9
|
|
|
@@ -77,10 +75,10 @@ class RSolr::Message
|
|
|
77
75
|
end
|
|
78
76
|
|
|
79
77
|
class << self
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def
|
|
83
|
-
::Builder
|
|
78
|
+
attr_writer :builder
|
|
79
|
+
|
|
80
|
+
def builder
|
|
81
|
+
@builder ||= Builders::Builder.new
|
|
84
82
|
end
|
|
85
83
|
|
|
86
84
|
# generates "add" xml for updating solr
|
|
@@ -108,59 +106,41 @@ class RSolr::Message
|
|
|
108
106
|
# The "nickname" field would have a boost="20.0"
|
|
109
107
|
# if the doc had a "nickname" field with the value of "Tim".
|
|
110
108
|
#
|
|
111
|
-
def add(data, add_attrs={}
|
|
109
|
+
def add(data, add_attrs={})
|
|
112
110
|
data = [data] unless data.is_a?(Array)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
yield doc if block_given?
|
|
118
|
-
add_node.doc(doc.attrs) do |doc_node|
|
|
119
|
-
doc.fields.each do |field_obj|
|
|
120
|
-
doc_node.field(field_obj.value, field_obj.attrs)
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
111
|
+
documents = data.map do |doc|
|
|
112
|
+
doc = Document.new(doc) if doc.respond_to?(:each_pair)
|
|
113
|
+
yield doc if block_given?
|
|
114
|
+
doc
|
|
124
115
|
end
|
|
116
|
+
builder.add(documents, add_attrs)
|
|
125
117
|
end
|
|
126
118
|
|
|
127
119
|
# generates a <commit/> message
|
|
128
120
|
def commit(opts={})
|
|
129
|
-
|
|
121
|
+
builder.commit(opts)
|
|
130
122
|
end
|
|
131
123
|
|
|
132
124
|
# generates a <optimize/> message
|
|
133
125
|
def optimize(opts={})
|
|
134
|
-
|
|
126
|
+
builder.optimize(opts)
|
|
135
127
|
end
|
|
136
128
|
|
|
137
129
|
# generates a <rollback/> message
|
|
138
130
|
def rollback
|
|
139
|
-
|
|
131
|
+
builder.rollback
|
|
140
132
|
end
|
|
141
133
|
|
|
142
134
|
# generates a <delete><id>ID</id></delete> message
|
|
143
135
|
# "ids" can be a single value or array of values
|
|
144
136
|
def delete_by_id(ids)
|
|
145
|
-
|
|
146
|
-
xml.delete do |xml|
|
|
147
|
-
ids.each do |id|
|
|
148
|
-
xml.id(id)
|
|
149
|
-
end
|
|
150
|
-
end
|
|
137
|
+
builder.delete_by_id(ids)
|
|
151
138
|
end
|
|
152
139
|
|
|
153
140
|
# generates a <delete><query>ID</query></delete> message
|
|
154
141
|
# "queries" can be a single value or an array of values
|
|
155
142
|
def delete_by_query(queries)
|
|
156
|
-
|
|
157
|
-
xml.delete do |xml|
|
|
158
|
-
queries.each do |query|
|
|
159
|
-
xml.query(query)
|
|
160
|
-
end
|
|
161
|
-
end
|
|
143
|
+
builder.delete_by_query(queries)
|
|
162
144
|
end
|
|
163
|
-
|
|
164
145
|
end
|
|
165
|
-
|
|
166
146
|
end
|
data/rsolr.gemspec
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = "rsolr"
|
|
3
|
-
s.version = "0.9.
|
|
4
|
-
s.date = "2009-07-
|
|
3
|
+
s.version = "0.9.1"
|
|
4
|
+
s.date = "2009-07-22"
|
|
5
5
|
s.summary = "A Ruby client for Apache Solr"
|
|
6
6
|
s.email = "goodieboy@gmail.com"
|
|
7
7
|
s.homepage = "http://github.com/mwmitchell/rsolr"
|
|
@@ -20,6 +20,9 @@ Gem::Specification.new do |s|
|
|
|
20
20
|
"lib/rsolr/http_client/adapter/net_http.rb",
|
|
21
21
|
"lib/rsolr/http_client/adapter.rb",
|
|
22
22
|
"lib/rsolr/http_client.rb",
|
|
23
|
+
"lib/rsolr/message/builders/builder.rb",
|
|
24
|
+
"lib/rsolr/message/builders/libxml.rb",
|
|
25
|
+
"lib/rsolr/message/builders.rb",
|
|
23
26
|
"lib/rsolr/message.rb",
|
|
24
27
|
"LICENSE",
|
|
25
28
|
"Rakefile",
|
data/test/message_test.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
require 'helper'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
module MessageTestMethods
|
|
5
5
|
|
|
6
6
|
# call all of the simple methods...
|
|
7
7
|
# make sure the xml string is valid
|
|
@@ -13,7 +13,7 @@ class MessageTest < RSolrBaseTest
|
|
|
13
13
|
assert_equal String, result.class
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def test_add_yields_doc_objects_if_block_given
|
|
18
18
|
documents = [{:id=>1, :name=>'sam', :cat=>['cat 1', 'cat 2']}]
|
|
19
19
|
add_attrs = {:boost=>200.00}
|
|
@@ -36,31 +36,31 @@ class MessageTest < RSolrBaseTest
|
|
|
36
36
|
assert result =~ %r(boost="10")
|
|
37
37
|
assert result =~ %r(<field name="id">1</field>)
|
|
38
38
|
end
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
def test_delete_by_id
|
|
41
41
|
result = RSolr::Message.delete_by_id(10)
|
|
42
42
|
assert_equal String, result.class
|
|
43
43
|
assert_equal '<delete><id>10</id></delete>', result.to_s
|
|
44
44
|
end
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
def test_delete_by_multiple_ids
|
|
47
47
|
result = RSolr::Message.delete_by_id([1, 2, 3])
|
|
48
48
|
assert_equal String, result.class
|
|
49
49
|
assert_equal '<delete><id>1</id><id>2</id><id>3</id></delete>', result.to_s
|
|
50
50
|
end
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
def test_delete_by_query
|
|
53
|
-
result = RSolr::Message.
|
|
53
|
+
result = RSolr::Message.delete_by_query('status:"LOST"')
|
|
54
54
|
assert_equal String, result.class
|
|
55
|
-
assert_equal '<delete><
|
|
55
|
+
assert_equal '<delete><query>status:"LOST"</query></delete>', result.to_s
|
|
56
56
|
end
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
def test_delete_by_multiple_queries
|
|
59
|
-
result = RSolr::Message.
|
|
59
|
+
result = RSolr::Message.delete_by_query(['status:"LOST"', 'quantity:0'])
|
|
60
60
|
assert_equal String, result.class
|
|
61
|
-
assert_equal '<delete><
|
|
61
|
+
assert_equal '<delete><query>status:"LOST"</query><query>quantity:0</query></delete>', result.to_s
|
|
62
62
|
end
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
# add a single hash ("doc")
|
|
65
65
|
def test_add_hash
|
|
66
66
|
data = {
|
|
@@ -70,7 +70,7 @@ class MessageTest < RSolrBaseTest
|
|
|
70
70
|
assert RSolr::Message.add(data).to_s =~ /<field name="name">matt<\/field>/
|
|
71
71
|
assert RSolr::Message.add(data).to_s =~ /<field name="id">1<\/field>/
|
|
72
72
|
end
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
# add an array of hashes
|
|
75
75
|
def test_add_array
|
|
76
76
|
data = [
|
|
@@ -83,35 +83,35 @@ class MessageTest < RSolrBaseTest
|
|
|
83
83
|
:name=>'sam'
|
|
84
84
|
}
|
|
85
85
|
]
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
message = RSolr::Message.add(data)
|
|
88
88
|
expected = '<add><doc><field name="id">1</field><field name="name">matt</field></doc><doc><field name="id">2</field><field name="name">sam</field></doc></add>'
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
assert message.to_s=~/<field name="name">matt<\/field>/
|
|
91
91
|
assert message.to_s=~/<field name="name">sam<\/field>/
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
# multiValue field support test, thanks to Fouad Mardini!
|
|
95
95
|
def test_add_multi_valued_field
|
|
96
96
|
data = {
|
|
97
97
|
:id => 1,
|
|
98
98
|
:name => ['matt1', 'matt2']
|
|
99
99
|
}
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
result = RSolr::Message.add(data)
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
assert result.to_s =~ /<field name="name">matt1<\/field>/
|
|
104
104
|
assert result.to_s =~ /<field name="name">matt2<\/field>/
|
|
105
105
|
end
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
def test_add_single_document
|
|
108
108
|
document = RSolr::Message::Document.new
|
|
109
109
|
document.add_field('id', 1)
|
|
110
110
|
document.add_field('name', 'matt', :boost => 2.0)
|
|
111
111
|
result = RSolr::Message.add(document)
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
assert result.to_s =~ /<field name="id">1<\/field>/
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
# depending on which ruby version, the attributes can be out of place
|
|
116
116
|
# so we need to test both... there's gotta be a better way to do this?
|
|
117
117
|
assert(
|
|
@@ -132,4 +132,33 @@ class MessageTest < RSolrBaseTest
|
|
|
132
132
|
assert result.to_s =~ /<field name="name">matt1<\/field>/
|
|
133
133
|
assert result.to_s =~ /<field name="name">matt2<\/field>/
|
|
134
134
|
end
|
|
135
|
+
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#####
|
|
139
|
+
|
|
140
|
+
unless defined?(JRUBY_VERSION)
|
|
141
|
+
class LibxmlMessageTest < RSolrBaseTest
|
|
142
|
+
|
|
143
|
+
include MessageTestMethods
|
|
144
|
+
|
|
145
|
+
def setup
|
|
146
|
+
RSolr::Message.builder = RSolr::Message::Builders::Libxml.new
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
end
|
|
135
150
|
end
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
#####
|
|
154
|
+
|
|
155
|
+
class BuilderMessageTest < RSolrBaseTest
|
|
156
|
+
|
|
157
|
+
include MessageTestMethods
|
|
158
|
+
|
|
159
|
+
def setup
|
|
160
|
+
# RSolr::Message::Builders::Libxml.new
|
|
161
|
+
RSolr::Message.builder = RSolr::Message::Builders::Builder.new
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mwmitchell-rsolr
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Mitchell
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-07-
|
|
12
|
+
date: 2009-07-22 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
@@ -45,6 +45,9 @@ files:
|
|
|
45
45
|
- lib/rsolr/http_client/adapter/net_http.rb
|
|
46
46
|
- lib/rsolr/http_client/adapter.rb
|
|
47
47
|
- lib/rsolr/http_client.rb
|
|
48
|
+
- lib/rsolr/message/builders/builder.rb
|
|
49
|
+
- lib/rsolr/message/builders/libxml.rb
|
|
50
|
+
- lib/rsolr/message/builders.rb
|
|
48
51
|
- lib/rsolr/message.rb
|
|
49
52
|
- LICENSE
|
|
50
53
|
- Rakefile
|