oauth-rsolr 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +14 -0
- data/README.rdoc +13 -0
- data/Rakefile +13 -0
- data/VERSION +1 -0
- data/lib/rsolr.rb +50 -0
- data/lib/rsolr/client.rb +116 -0
- data/lib/rsolr/connection.rb +9 -0
- data/lib/rsolr/connection/net_http.rb +98 -0
- data/lib/rsolr/connection/requestable.rb +43 -0
- data/lib/rsolr/connection/utils.rb +106 -0
- data/lib/rsolr/message.rb +8 -0
- data/lib/rsolr/message/document.rb +48 -0
- data/lib/rsolr/message/field.rb +20 -0
- data/lib/rsolr/message/generator.rb +89 -0
- data/oauth-rsolr.gemspec +36 -0
- metadata +117 -0
data/Manifest
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
README.rdoc
|
2
|
+
Rakefile
|
3
|
+
VERSION
|
4
|
+
lib/rsolr.rb
|
5
|
+
lib/rsolr/client.rb
|
6
|
+
lib/rsolr/connection.rb
|
7
|
+
lib/rsolr/connection/net_http.rb
|
8
|
+
lib/rsolr/connection/requestable.rb
|
9
|
+
lib/rsolr/connection/utils.rb
|
10
|
+
lib/rsolr/message.rb
|
11
|
+
lib/rsolr/message/document.rb
|
12
|
+
lib/rsolr/message/field.rb
|
13
|
+
lib/rsolr/message/generator.rb
|
14
|
+
Manifest
|
data/README.rdoc
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
= tsxn-rsolr
|
2
|
+
|
3
|
+
A simple, extensible Ruby client for Apache Solr. MODIFIED/CUSTOMIZED to add OAuth request signing for POST requests to support 2-legged OAuth.
|
4
|
+
|
5
|
+
== Credits
|
6
|
+
|
7
|
+
The original gem was written by Matt Mitchell and is located at http://github.com/mwmitchell/rsolr.
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
See the usage of the original gem at http://github.com/mwmitchell/rsolr.
|
12
|
+
|
13
|
+
The additional setup requires that the OAuth consumer key be specified in ENV["oauth_key"] and the OAuth consumer secret be specified in ENV["oauth_secret"]. Only HMAC-SHA1 is supported.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('oauth-rsolr', '0.12.1') do |p|
|
6
|
+
p.description = "RSolr aims to provide a simple and extensible library for working with Solr. This is a CUSTOMIZED version that OAuth signs every POST request for 2-legged OAuth. Only supports HMAC-SHA1. The original gem was written by Matt Mitchell and is located at http://github.com/mwmitchell/rsolr."
|
7
|
+
p.url = "http://github.com/tsxn26/tsxn-rsolr"
|
8
|
+
p.author = ["Matt Mitchell", "Thomas Nguyen"]
|
9
|
+
p.email = "tsxn26@gmail.com"
|
10
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
11
|
+
p.development_dependencies = []
|
12
|
+
p.runtime_dependencies = ["builder >=2.1.2", "ruby-hmac"]
|
13
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.12.1
|
data/lib/rsolr.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
$:.unshift File.dirname(__FILE__) unless $:.include?(File.dirname(__FILE__))
|
4
|
+
|
5
|
+
module RSolr
|
6
|
+
|
7
|
+
def self.version
|
8
|
+
@version ||= File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
|
9
|
+
end
|
10
|
+
|
11
|
+
VERSION = self.version
|
12
|
+
|
13
|
+
autoload :Message, 'rsolr/message'
|
14
|
+
autoload :Client, 'rsolr/client'
|
15
|
+
autoload :Connection, 'rsolr/connection'
|
16
|
+
|
17
|
+
module Connectable
|
18
|
+
|
19
|
+
def connect opts={}
|
20
|
+
Client.new Connection::NetHttp.new(opts)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
extend Connectable
|
26
|
+
|
27
|
+
# A module that contains string related methods
|
28
|
+
module Char
|
29
|
+
|
30
|
+
# escape - from the solr-ruby library
|
31
|
+
# RSolr.escape('asdf')
|
32
|
+
# backslash everything that isn't a word character
|
33
|
+
def escape(value)
|
34
|
+
value.gsub(/(\W)/, '\\\\\1')
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# send the escape method into the Connection class ->
|
40
|
+
# solr = RSolr.connect
|
41
|
+
# solr.escape('asdf')
|
42
|
+
RSolr::Client.send(:include, Char)
|
43
|
+
|
44
|
+
# bring escape into this module (RSolr) -> RSolr.escape('asdf')
|
45
|
+
extend Char
|
46
|
+
|
47
|
+
# RequestError is a common/generic exception class used by the adapters
|
48
|
+
class RequestError < RuntimeError; end
|
49
|
+
|
50
|
+
end
|
data/lib/rsolr/client.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
class RSolr::Client
|
2
|
+
|
3
|
+
attr_reader :connection
|
4
|
+
|
5
|
+
# "connection" is instance of:
|
6
|
+
# RSolr::Adapter::HTTP
|
7
|
+
# RSolr::Adapter::Direct (jRuby only)
|
8
|
+
# or any other class that uses the connection "interface"
|
9
|
+
def initialize(connection)
|
10
|
+
@connection = connection
|
11
|
+
end
|
12
|
+
|
13
|
+
# Send a request to a request handler using the method name.
|
14
|
+
# Also proxies to the #paginate method if the method starts with "paginate_"
|
15
|
+
def method_missing(method_name, *args, &blk)
|
16
|
+
request("/#{method_name}", *args, &blk)
|
17
|
+
end
|
18
|
+
|
19
|
+
# sends data to the update handler
|
20
|
+
# data can be a string of xml, or an object that returns xml from its #to_xml method
|
21
|
+
def update(data, params={})
|
22
|
+
params.merge!({"oauth_signature_method"=>"HMAC-SHA1", "oauth_timestamp"=>Time.now.to_i.to_s, "oauth_nonce"=>Time.now.to_i.to_s})
|
23
|
+
params.merge!({"oauth_consumer_key"=>ENV["oauth_key"], "oauth_version"=>"1.0"})
|
24
|
+
request '/update', params, data
|
25
|
+
end
|
26
|
+
|
27
|
+
# send request solr
|
28
|
+
# params is hash with valid solr request params (:q, :fl, :qf etc..)
|
29
|
+
# if params[:wt] is not set, the default is :ruby
|
30
|
+
# if :wt is something other than :ruby, the raw response body is used
|
31
|
+
# otherwise, a simple Hash is returned
|
32
|
+
# NOTE: to get raw ruby, use :wt=>'ruby' <- a string, not a symbol like :ruby
|
33
|
+
#
|
34
|
+
#
|
35
|
+
def request(path, params={}, *extra)
|
36
|
+
response = @connection.request(path, map_params(params), *extra)
|
37
|
+
adapt_response(response)
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# single record:
|
42
|
+
# solr.update(:id=>1, :name=>'one')
|
43
|
+
#
|
44
|
+
# update using an array
|
45
|
+
# solr.update([{:id=>1, :name=>'one'}, {:id=>2, :name=>'two'}])
|
46
|
+
#
|
47
|
+
def add(doc, &block)
|
48
|
+
update message.add(doc, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
# send </commit>
|
52
|
+
def commit
|
53
|
+
update message.commit
|
54
|
+
end
|
55
|
+
|
56
|
+
# send </optimize>
|
57
|
+
def optimize
|
58
|
+
update message.optimize
|
59
|
+
end
|
60
|
+
|
61
|
+
# send </rollback>
|
62
|
+
# NOTE: solr 1.4 only
|
63
|
+
def rollback
|
64
|
+
update message.rollback
|
65
|
+
end
|
66
|
+
|
67
|
+
# Delete one or many documents by id
|
68
|
+
# solr.delete_by_id 10
|
69
|
+
# solr.delete_by_id([12, 41, 199])
|
70
|
+
def delete_by_id(id)
|
71
|
+
update message.delete_by_id(id)
|
72
|
+
end
|
73
|
+
|
74
|
+
# delete one or many documents by query
|
75
|
+
# solr.delete_by_query 'available:0'
|
76
|
+
# solr.delete_by_query ['quantity:0', 'manu:"FQ"']
|
77
|
+
def delete_by_query(query)
|
78
|
+
update message.delete_by_query(query)
|
79
|
+
end
|
80
|
+
|
81
|
+
# shortcut to RSolr::Message::Generator
|
82
|
+
def message *opts
|
83
|
+
@message ||= RSolr::Message::Generator.new
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
# sets default params etc.. - could be used as a mapping hook
|
89
|
+
# type of request should be passed in here? -> map_params(:query, {})
|
90
|
+
def map_params(params)
|
91
|
+
params||={}
|
92
|
+
{:wt=>:ruby}.merge(params)
|
93
|
+
end
|
94
|
+
|
95
|
+
# "connection_response" must be a hash with the following keys:
|
96
|
+
# :params - a sub hash of standard solr params
|
97
|
+
# : body - the raw response body from the solr server
|
98
|
+
# This method will evaluate the :body value if the params[:wt] == :ruby
|
99
|
+
# otherwise, the body is returned
|
100
|
+
# The return object has a special method attached called #raw
|
101
|
+
# This method gives you access to the original response from the connection,
|
102
|
+
# so you can access things like the actual :url sent to solr,
|
103
|
+
# the raw :body, original :params and original :data
|
104
|
+
def adapt_response(connection_response)
|
105
|
+
data = connection_response[:body]
|
106
|
+
# if the wt is :ruby, evaluate the ruby string response
|
107
|
+
if connection_response[:params][:wt] == :ruby
|
108
|
+
data = Kernel.eval(data)
|
109
|
+
end
|
110
|
+
# attach a method called #raw that returns the original connection response value
|
111
|
+
def data.raw; @raw end
|
112
|
+
data.send(:instance_variable_set, '@raw', connection_response)
|
113
|
+
data
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'hmac-sha1'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Connection for standard HTTP Solr server
|
6
|
+
#
|
7
|
+
class RSolr::Connection::NetHttp
|
8
|
+
|
9
|
+
include RSolr::Connection::Requestable
|
10
|
+
|
11
|
+
def connection
|
12
|
+
@connection ||= Net::HTTP.new(@uri.host, @uri.port)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get path, params={}
|
16
|
+
url = self.build_url path, params
|
17
|
+
net_http_response = self.connection.get url
|
18
|
+
create_http_context net_http_response, url, path, params
|
19
|
+
end
|
20
|
+
|
21
|
+
def post path, data, params={}, headers={}
|
22
|
+
add_signature("POST", path, params)
|
23
|
+
|
24
|
+
url = self.build_url path, params
|
25
|
+
net_http_response = self.connection.post url, data, headers
|
26
|
+
create_http_context net_http_response, url, path, params, data, headers
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_http_context net_http_response, url, path, params, data=nil, headers={}
|
30
|
+
full_url = "#{@uri.scheme}://#{@uri.host}"
|
31
|
+
full_url += @uri.port ? ":#{@uri.port}" : ''
|
32
|
+
full_url += url
|
33
|
+
{
|
34
|
+
:status_code=>net_http_response.code.to_i,
|
35
|
+
:url=>full_url,
|
36
|
+
:body=> encode_utf8(net_http_response.body),
|
37
|
+
:path=>path,
|
38
|
+
:params=>params,
|
39
|
+
:data=>data,
|
40
|
+
:headers=>headers,
|
41
|
+
:message => net_http_response.message
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
# accepts a path/string and optional hash of query params
|
46
|
+
def build_url path, params={}
|
47
|
+
full_path = @uri.path + path
|
48
|
+
super full_path, params, @uri.query
|
49
|
+
end
|
50
|
+
|
51
|
+
def normalize_params(params)
|
52
|
+
return_string = ""
|
53
|
+
params.keys.sort{|x,y| x.to_s <=> y.to_s}.each do |k|
|
54
|
+
v = params[k]
|
55
|
+
if v.class == Array
|
56
|
+
v.sort.each {|v| return_string.concat("#{k.to_s}=#{v}&")}
|
57
|
+
else
|
58
|
+
return_string.concat("#{k.to_s}=#{v}&")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
if !return_string.blank?
|
62
|
+
return_string.chop!
|
63
|
+
end
|
64
|
+
return_string
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_base_string(method, path, params)
|
68
|
+
url = "#{@uri.scheme}://#{@uri.host}"
|
69
|
+
port = @uri.port.to_s
|
70
|
+
if !port.blank?
|
71
|
+
if port != "80"
|
72
|
+
url += ":#{port}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
url += @uri.path + path
|
76
|
+
signature_base = method.upcase
|
77
|
+
signature_base.concat("&")
|
78
|
+
signature_base.concat(CGI::escape(url))
|
79
|
+
signature_base.concat("&")
|
80
|
+
signature_base.concat(CGI::escape(normalize_params(params)))
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_signature(base_string, consumer_secret, token_secret="")
|
84
|
+
secret = "#{escape(consumer_secret)}&#{escape(token_secret)}"
|
85
|
+
Base64.encode64(HMAC::SHA1.digest(secret, base_string)).chomp.gsub(/\n/,'')
|
86
|
+
end
|
87
|
+
|
88
|
+
def escape(value)
|
89
|
+
CGI.escape(value.to_s).gsub("%7E", '~').gsub("+", "%20")
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_signature(http_method, path, params)
|
93
|
+
base_string = create_base_string(http_method, path, params)
|
94
|
+
signature = create_signature(base_string, ENV["oauth_secret"])
|
95
|
+
params.merge!("oauth_signature" => signature)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# A module that defines the interface and top-level logic for http based connection classes.
|
2
|
+
module RSolr::Connection::Requestable
|
3
|
+
|
4
|
+
include RSolr::Connection::Utils
|
5
|
+
|
6
|
+
attr_reader :opts, :uri
|
7
|
+
|
8
|
+
# opts can have:
|
9
|
+
# :url => 'http://localhost:8080/solr'
|
10
|
+
def initialize opts={}
|
11
|
+
opts[:url] ||= 'http://127.0.0.1:8983/solr'
|
12
|
+
@opts = opts
|
13
|
+
@uri = URI.parse opts[:url]
|
14
|
+
end
|
15
|
+
|
16
|
+
# send a request to the connection
|
17
|
+
# request '/select', :q=>'*:*'
|
18
|
+
#
|
19
|
+
# request '/update', {:wt=>:xml}, '</commit>'
|
20
|
+
#
|
21
|
+
# force a post where the post body is the param query
|
22
|
+
# request '/update', "<optimize/>", :method=>:post
|
23
|
+
#
|
24
|
+
def request path, params={}, *extra
|
25
|
+
opts = extra[-1].kind_of?(Hash) ? extra.pop : {}
|
26
|
+
data = extra[0]
|
27
|
+
# force a POST, use the query string as the POST body
|
28
|
+
if opts[:method] == :post and data.to_s.empty?
|
29
|
+
http_context = self.post(path, hash_to_query(params), {}, {'Content-Type' => 'application/x-www-form-urlencoded'})
|
30
|
+
else
|
31
|
+
if data
|
32
|
+
# standard POST, using "data" as the POST body
|
33
|
+
http_context = self.post(path, data, params, {"Content-Type" => 'text/xml; charset=utf-8'})
|
34
|
+
else
|
35
|
+
# standard GET
|
36
|
+
http_context = self.get(path, params)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
raise RSolr::RequestError.new("Solr Response: #{http_context[:message]}") unless http_context[:status_code] == 200
|
40
|
+
http_context
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Helpful utility methods for building queries to a Solr server
|
2
|
+
# This includes helpers that the Direct connection can use.
|
3
|
+
module RSolr::Connection::Utils
|
4
|
+
|
5
|
+
# Performs URI escaping so that you can construct proper
|
6
|
+
# query strings faster. Use this rather than the cgi.rb
|
7
|
+
# version since it's faster. (Stolen from Rack).
|
8
|
+
def escape(s)
|
9
|
+
s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
|
10
|
+
#'%'+$1.unpack('H2'*$1.size).join('%').upcase
|
11
|
+
'%'+$1.unpack('H2'*bytesize($1)).join('%').upcase
|
12
|
+
}.tr(' ', '+')
|
13
|
+
end
|
14
|
+
|
15
|
+
# encodes the string as utf-8 in Ruby 1.9
|
16
|
+
# returns the unaltered string in Ruby 1.8
|
17
|
+
def encode_utf8 string
|
18
|
+
(string.respond_to?(:force_encoding) and string.respond_to?(:encoding)) ?
|
19
|
+
string.force_encoding(Encoding::UTF_8) : string
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return the bytesize of String; uses String#length under Ruby 1.8 and
|
23
|
+
# String#bytesize under 1.9.
|
24
|
+
if ''.respond_to?(:bytesize)
|
25
|
+
def bytesize(string)
|
26
|
+
string.bytesize
|
27
|
+
end
|
28
|
+
else
|
29
|
+
def bytesize(string)
|
30
|
+
string.size
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# creates and returns a url as a string
|
35
|
+
# "url" is the base url
|
36
|
+
# "params" is an optional hash of GET style query params
|
37
|
+
# "string_query" is an extra query string that will be appended to the
|
38
|
+
# result of "url" and "params".
|
39
|
+
def build_url url='', params={}, string_query=''
|
40
|
+
queries = [string_query, hash_to_query(params)]
|
41
|
+
queries.delete_if{|i| i.to_s.empty?}
|
42
|
+
url += "?#{queries.join('&')}" unless queries.empty?
|
43
|
+
url
|
44
|
+
end
|
45
|
+
|
46
|
+
# converts a key value pair to an escaped string:
|
47
|
+
# Example:
|
48
|
+
# build_param(:id, 1) == "id=1"
|
49
|
+
def build_param(k,v)
|
50
|
+
"#{escape(k)}=#{escape(v)}"
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# converts hash into URL query string, keys get an alpha sort
|
55
|
+
# if a value is an array, the array values get mapped to the same key:
|
56
|
+
# hash_to_query(:q=>'blah', :fq=>['blah', 'blah'], :facet=>{:field=>['location_facet', 'format_facet']})
|
57
|
+
# returns:
|
58
|
+
# ?q=blah&fq=blah&fq=blah&facet.field=location_facet&facet.field=format.facet
|
59
|
+
#
|
60
|
+
# if a value is empty/nil etc., it is not added
|
61
|
+
def hash_to_query(params)
|
62
|
+
mapped = params.map do |k, v|
|
63
|
+
next if v.to_s.empty?
|
64
|
+
if v.class == Array
|
65
|
+
hash_to_query(v.map { |x| [k, x] })
|
66
|
+
else
|
67
|
+
build_param k, v
|
68
|
+
end
|
69
|
+
end
|
70
|
+
mapped.compact.join("&")
|
71
|
+
end
|
72
|
+
|
73
|
+
def normalize_params(params)
|
74
|
+
return_string = ""
|
75
|
+
params.keys.sort.each do |k|
|
76
|
+
v = params[k]
|
77
|
+
if v.class == Array
|
78
|
+
v.sort.each {|v| return_string.concat("#{k}=#{v}&")}
|
79
|
+
else
|
80
|
+
return_string.concat("#{k}=#{v}&")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
if !return_string.blank?
|
84
|
+
return_string.chop!
|
85
|
+
end
|
86
|
+
return_string
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_base_string(method, url, params)
|
90
|
+
signature_base = method.upcase
|
91
|
+
signature_base.concat("&")
|
92
|
+
signature_base.concat(CGI::escape(url))
|
93
|
+
signature_base.concat("&")
|
94
|
+
signature_base.concat(CGI::escape(normalize_params(params)))
|
95
|
+
end
|
96
|
+
|
97
|
+
def create_signature(base_string, consumer_secret, token_secret="")
|
98
|
+
require "hmac-sha1"
|
99
|
+
secret = "#{escape(consumer_secret)}&#{escape(token_secret)}"
|
100
|
+
Base64.encode64(HMAC::SHA1.digest(secret, base_string)).chomp.gsub(/\n/,'')
|
101
|
+
end
|
102
|
+
|
103
|
+
def escape(value)
|
104
|
+
CGI.escape(value.to_s).gsub("%7E", '~').gsub("+", "%20")
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# A class that represents a "doc" xml element for a solr update
|
2
|
+
class RSolr::Message::Document
|
3
|
+
|
4
|
+
# "attrs" is a hash for setting the "doc" xml attributes
|
5
|
+
# "fields" is an array of Field objects
|
6
|
+
attr_accessor :attrs, :fields
|
7
|
+
|
8
|
+
# "doc_hash" must be a Hash/Mash object
|
9
|
+
# If a value in the "doc_hash" is an array,
|
10
|
+
# a field object is created for each value...
|
11
|
+
def initialize(doc_hash = {})
|
12
|
+
@fields = []
|
13
|
+
doc_hash.each_pair do |field,values|
|
14
|
+
# create a new field for each value (multi-valued)
|
15
|
+
# put non-array values into an array
|
16
|
+
values = [values] unless values.is_a?(Array)
|
17
|
+
values.each do |v|
|
18
|
+
next if v.to_s.empty?
|
19
|
+
@fields << RSolr::Message::Field.new({:name=>field}, v.to_s)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
@attrs={}
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns an array of fields that match the "name" arg
|
26
|
+
def fields_by_name(name)
|
27
|
+
@fields.select{|f|f.name==name}
|
28
|
+
end
|
29
|
+
|
30
|
+
# returns the *first* field that matches the "name" arg
|
31
|
+
def field_by_name(name)
|
32
|
+
@fields.detect{|f|f.name==name}
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Add a field value to the document. Options map directly to
|
37
|
+
# XML attributes in the Solr <field> node.
|
38
|
+
# See http://wiki.apache.org/solr/UpdateXmlMessages#head-8315b8028923d028950ff750a57ee22cbf7977c6
|
39
|
+
#
|
40
|
+
# === Example:
|
41
|
+
#
|
42
|
+
# document.add_field('title', 'A Title', :boost => 2.0)
|
43
|
+
#
|
44
|
+
def add_field(name, value, options = {})
|
45
|
+
@fields << RSolr::Message::Field.new(options.merge({:name=>name}), value)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# A class that represents a "doc"/"field" xml element for a solr update
|
2
|
+
class RSolr::Message::Field
|
3
|
+
|
4
|
+
# "attrs" is a hash for setting the "doc" xml attributes
|
5
|
+
# "value" is the text value for the node
|
6
|
+
attr_accessor :attrs, :value
|
7
|
+
|
8
|
+
# "attrs" must be a hash
|
9
|
+
# "value" should be something that responds to #_to_s
|
10
|
+
def initialize(attrs, value)
|
11
|
+
@attrs = attrs
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
# the value of the "name" attribute
|
16
|
+
def name
|
17
|
+
@attrs[:name]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class RSolr::Message::Generator
|
2
|
+
|
3
|
+
def build &block
|
4
|
+
require 'builder'
|
5
|
+
b = ::Builder::XmlMarkup.new(:indent=>0, :margin=>0, :encoding => 'UTF-8')
|
6
|
+
b.instruct!
|
7
|
+
block_given? ? yield(b) : b
|
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 data, add_attrs={}, &block
|
36
|
+
data = [data] unless data.is_a?(Array)
|
37
|
+
build do |xml|
|
38
|
+
xml.add(add_attrs) do |add_node|
|
39
|
+
data.each do |doc|
|
40
|
+
doc = RSolr::Message::Document.new(doc) if doc.respond_to?(:each_pair)
|
41
|
+
yield doc if block_given?
|
42
|
+
add_node.doc(doc.attrs) do |doc_node|
|
43
|
+
doc.fields.each do |field_obj|
|
44
|
+
doc_node.field field_obj.value, field_obj.attrs
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# generates a <commit/> message
|
53
|
+
def commit(opts={})
|
54
|
+
build {|xml| xml.commit opts}
|
55
|
+
end
|
56
|
+
|
57
|
+
# generates a <optimize/> message
|
58
|
+
def optimize(opts={})
|
59
|
+
build {|xml| xml.optimize opts}
|
60
|
+
end
|
61
|
+
|
62
|
+
# generates a <rollback/> message
|
63
|
+
def rollback opts={}
|
64
|
+
build {|xml| xml.rollback opts}
|
65
|
+
end
|
66
|
+
|
67
|
+
# generates a <delete><id>ID</id></delete> message
|
68
|
+
# "ids" can be a single value or array of values
|
69
|
+
def delete_by_id(ids)
|
70
|
+
ids = [ids] unless ids.is_a?(Array)
|
71
|
+
build do |xml|
|
72
|
+
xml.delete do |delete_node|
|
73
|
+
ids.each { |id| delete_node.id(id) }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# generates a <delete><query>ID</query></delete> message
|
79
|
+
# "queries" can be a single value or an array of values
|
80
|
+
def delete_by_query(queries)
|
81
|
+
queries = [queries] unless queries.is_a?(Array)
|
82
|
+
build do |xml|
|
83
|
+
xml.delete do |delete_node|
|
84
|
+
queries.each { |query| delete_node.query query }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/oauth-rsolr.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{oauth-rsolr}
|
5
|
+
s.version = "0.12.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Matt Mitchell, Thomas Nguyen"]
|
9
|
+
s.date = %q{2010-04-13}
|
10
|
+
s.description = %q{RSolr aims to provide a simple and extensible library for working with Solr. This is a CUSTOMIZED version that OAuth signs every POST request for 2-legged OAuth. Only supports HMAC-SHA1. The original gem was written by Matt Mitchell and is located at http://github.com/mwmitchell/rsolr.}
|
11
|
+
s.email = %q{tsxn26@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["README.rdoc", "lib/rsolr.rb", "lib/rsolr/client.rb", "lib/rsolr/connection.rb", "lib/rsolr/connection/net_http.rb", "lib/rsolr/connection/requestable.rb", "lib/rsolr/connection/utils.rb", "lib/rsolr/message.rb", "lib/rsolr/message/document.rb", "lib/rsolr/message/field.rb", "lib/rsolr/message/generator.rb"]
|
13
|
+
s.files = ["README.rdoc", "Rakefile", "VERSION", "lib/rsolr.rb", "lib/rsolr/client.rb", "lib/rsolr/connection.rb", "lib/rsolr/connection/net_http.rb", "lib/rsolr/connection/requestable.rb", "lib/rsolr/connection/utils.rb", "lib/rsolr/message.rb", "lib/rsolr/message/document.rb", "lib/rsolr/message/field.rb", "lib/rsolr/message/generator.rb", "Manifest", "oauth-rsolr.gemspec"]
|
14
|
+
s.homepage = %q{http://github.com/tsxn26/tsxn-rsolr}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Oauth-rsolr", "--main", "README.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{oauth-rsolr}
|
18
|
+
s.rubygems_version = %q{1.3.6}
|
19
|
+
s.summary = %q{RSolr aims to provide a simple and extensible library for working with Solr. This is a CUSTOMIZED version that OAuth signs every POST request for 2-legged OAuth. Only supports HMAC-SHA1. The original gem was written by Matt Mitchell and is located at http://github.com/mwmitchell/rsolr.}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_runtime_dependency(%q<builder>, [">= 2.1.2"])
|
27
|
+
s.add_runtime_dependency(%q<ruby-hmac>, [">= 0"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<builder>, [">= 2.1.2"])
|
30
|
+
s.add_dependency(%q<ruby-hmac>, [">= 0"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<builder>, [">= 2.1.2"])
|
34
|
+
s.add_dependency(%q<ruby-hmac>, [">= 0"])
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oauth-rsolr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 12
|
8
|
+
- 1
|
9
|
+
version: 0.12.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Matt Mitchell, Thomas Nguyen
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-13 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: builder
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 1
|
30
|
+
- 2
|
31
|
+
version: 2.1.2
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: ruby-hmac
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
description: RSolr aims to provide a simple and extensible library for working with Solr. This is a CUSTOMIZED version that OAuth signs every POST request for 2-legged OAuth. Only supports HMAC-SHA1. The original gem was written by Matt Mitchell and is located at http://github.com/mwmitchell/rsolr.
|
47
|
+
email: tsxn26@gmail.com
|
48
|
+
executables: []
|
49
|
+
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
extra_rdoc_files:
|
53
|
+
- README.rdoc
|
54
|
+
- lib/rsolr.rb
|
55
|
+
- lib/rsolr/client.rb
|
56
|
+
- lib/rsolr/connection.rb
|
57
|
+
- lib/rsolr/connection/net_http.rb
|
58
|
+
- lib/rsolr/connection/requestable.rb
|
59
|
+
- lib/rsolr/connection/utils.rb
|
60
|
+
- lib/rsolr/message.rb
|
61
|
+
- lib/rsolr/message/document.rb
|
62
|
+
- lib/rsolr/message/field.rb
|
63
|
+
- lib/rsolr/message/generator.rb
|
64
|
+
files:
|
65
|
+
- README.rdoc
|
66
|
+
- Rakefile
|
67
|
+
- VERSION
|
68
|
+
- lib/rsolr.rb
|
69
|
+
- lib/rsolr/client.rb
|
70
|
+
- lib/rsolr/connection.rb
|
71
|
+
- lib/rsolr/connection/net_http.rb
|
72
|
+
- lib/rsolr/connection/requestable.rb
|
73
|
+
- lib/rsolr/connection/utils.rb
|
74
|
+
- lib/rsolr/message.rb
|
75
|
+
- lib/rsolr/message/document.rb
|
76
|
+
- lib/rsolr/message/field.rb
|
77
|
+
- lib/rsolr/message/generator.rb
|
78
|
+
- Manifest
|
79
|
+
- oauth-rsolr.gemspec
|
80
|
+
has_rdoc: true
|
81
|
+
homepage: http://github.com/tsxn26/tsxn-rsolr
|
82
|
+
licenses: []
|
83
|
+
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options:
|
86
|
+
- --line-numbers
|
87
|
+
- --inline-source
|
88
|
+
- --title
|
89
|
+
- Oauth-rsolr
|
90
|
+
- --main
|
91
|
+
- README.rdoc
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
version: "0"
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
segments:
|
106
|
+
- 1
|
107
|
+
- 2
|
108
|
+
version: "1.2"
|
109
|
+
requirements: []
|
110
|
+
|
111
|
+
rubyforge_project: oauth-rsolr
|
112
|
+
rubygems_version: 1.3.6
|
113
|
+
signing_key:
|
114
|
+
specification_version: 3
|
115
|
+
summary: RSolr aims to provide a simple and extensible library for working with Solr. This is a CUSTOMIZED version that OAuth signs every POST request for 2-legged OAuth. Only supports HMAC-SHA1. The original gem was written by Matt Mitchell and is located at http://github.com/mwmitchell/rsolr.
|
116
|
+
test_files: []
|
117
|
+
|