oauth-rsolr 0.12.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/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
|
+
|