mwmitchell-rsolr 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +5 -0
- data/README.rdoc +2 -2
- data/examples/direct.rb +1 -1
- data/examples/http.rb +1 -1
- data/lib/rsolr.rb +1 -2
- data/lib/rsolr/connection/adapter/http.rb +1 -1
- data/lib/rsolr/connection/base.rb +12 -1
- data/lib/rsolr/http_client.rb +1 -3
- data/lib/rsolr/http_client/adapter/curb.rb +12 -12
- data/lib/rsolr/http_client/adapter/net_http.rb +5 -5
- metadata +2 -5
- data/lib/rsolr/indexer.rb +0 -23
- data/lib/rsolr/mapper.rb +0 -62
- data/lib/rsolr/mapper/rss.rb +0 -29
- data/test/mapper_test.rb +0 -123
data/CHANGES.txt
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
0.6.2 - January 14, 2009
|
2
|
+
Removed mapping and indexer modules -- seems to me that a general purpose mapping library
|
3
|
+
would be more valuable than an embedded module in RSolr ( RMapper ?)
|
4
|
+
This helps lighten RSolr a bit too
|
5
|
+
|
1
6
|
0.6.1 - January 13, 2009
|
2
7
|
Removed SearchExt and mapping until this library gets some real use
|
3
8
|
The only param mapping now is for :page and :per_page via the #search method
|
data/README.rdoc
CHANGED
@@ -59,9 +59,9 @@ If you use WillPaginate, just pass-in the response to the #will_paginate view he
|
|
59
59
|
|
60
60
|
<%= will_paginate(@response) %>
|
61
61
|
|
62
|
-
The #search method automatically
|
62
|
+
The #search method automatically figures out the :start and :rows values, based on the values of :page and :per_page. The will_paginate view helper uses the methods: #current_page, #previous_page, #next_page and #total_pages to create the pagination view widget.
|
63
63
|
|
64
|
-
The #search method will be providing more param mapping, but not until RSolr gets more use. If you have ideas for a param mapping interface, let me know!
|
64
|
+
The #search method will be providing more param mapping, but not until RSolr gets more use. If you have ideas for a param mapping interface, let me know! I'll be throwing some stuff together as well.
|
65
65
|
|
66
66
|
|
67
67
|
=== Updating Solr
|
data/examples/direct.rb
CHANGED
@@ -9,7 +9,7 @@ solr = RSolr.connect(:direct, :home_dir=>home, :dist_dir=>dist)
|
|
9
9
|
|
10
10
|
`cd ../apache-solr/example/exampledocs && ./post.sh ./*.xml`
|
11
11
|
|
12
|
-
response = solr.search 'ipod', :
|
12
|
+
response = solr.search :q=>'ipod', :fq=>'price:[0 TO 50]', :per_page=>2, :page=>1
|
13
13
|
|
14
14
|
solr.delete_by_query('*:*')
|
15
15
|
|
data/examples/http.rb
CHANGED
@@ -5,7 +5,7 @@ solr = RSolr.connect(:http)
|
|
5
5
|
|
6
6
|
`cd ../apache-solr/example/exampledocs && ./post.sh ./*.xml`
|
7
7
|
|
8
|
-
response = solr.search 'ipod', :
|
8
|
+
response = solr.search :q=>'ipod', :fq=>'price:[0 TO 50]', :per_page=>2, :page=>1
|
9
9
|
|
10
10
|
solr.delete_by_query('*:*')
|
11
11
|
|
data/lib/rsolr.rb
CHANGED
@@ -7,12 +7,11 @@ proc {|base, files|
|
|
7
7
|
|
8
8
|
module RSolr
|
9
9
|
|
10
|
-
VERSION = '0.6.
|
10
|
+
VERSION = '0.6.2'
|
11
11
|
|
12
12
|
autoload :Message, 'rsolr/message'
|
13
13
|
autoload :Response, 'rsolr/response'
|
14
14
|
autoload :Connection, 'rsolr/connection'
|
15
|
-
autoload :Mapper, 'rsolr/mapper'
|
16
15
|
autoload :Indexer, 'rsolr/indexer'
|
17
16
|
autoload :HTTPClient, 'rsolr/http_client'
|
18
17
|
|
@@ -21,7 +21,7 @@ class RSolr::Connection::Adapter::HTTP
|
|
21
21
|
#
|
22
22
|
def initialize(opts={}, &block)
|
23
23
|
opts[:url]||='http://127.0.0.1:8983/solr'
|
24
|
-
@opts = default_options.merge(opts)
|
24
|
+
@opts = default_options.merge(opts) # default_options are coming from RSolr::Connection::Adapter::CommonMethods
|
25
25
|
end
|
26
26
|
|
27
27
|
def connection
|
@@ -41,6 +41,8 @@ class RSolr::Connection::Base
|
|
41
41
|
|
42
42
|
# same as the #query method, but with additional param mapping
|
43
43
|
# currently only :page and :per_page
|
44
|
+
# TODO: need to get some nice and friendly param mapping here:
|
45
|
+
# search(:fields=>'', :facet_fields=>[], :filters=>{})
|
44
46
|
def search(params)
|
45
47
|
self.query(modify_params_for_pagination(params))
|
46
48
|
end
|
@@ -108,9 +110,18 @@ class RSolr::Connection::Base
|
|
108
110
|
RSolr::Message
|
109
111
|
end
|
110
112
|
|
113
|
+
# given a hash, this method will attempt to produce the
|
114
|
+
# correct :start and :rows values for Solr
|
115
|
+
# -- if the hash contains a :per_page value, it's used for the rows
|
116
|
+
# if the :per_page value doesn't exist (nil), the :rows value is
|
117
|
+
# used, and if :rows is not set, the default value is 10
|
118
|
+
# -- if the hash contains a :page value (the current page)
|
119
|
+
# it is used to calculate the :start value
|
120
|
+
# returns a hash with the :rows and :start values
|
121
|
+
# :per_page and :page are deleted
|
111
122
|
def modify_params_for_pagination(p)
|
112
123
|
per_page = p.delete(:per_page).to_s.to_i
|
113
|
-
p[:rows] = per_page==0 ? 10 : per_page
|
124
|
+
p[:rows] = per_page==0 ? (p[:rows] || 10) : per_page
|
114
125
|
page = p.delete(:page).to_s.to_i
|
115
126
|
page = page > 0 ? page : 1
|
116
127
|
p[:start] = (page - 1) * (p[:rows] || 0)
|
data/lib/rsolr/http_client.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
#require 'uri'
|
2
|
-
|
3
1
|
# A simple wrapper for different http client implementations.
|
4
2
|
# Supports #get and #post
|
5
3
|
# This was motivated by: http://apocryph.org/2008/11/09/more_indepth_analysis_ruby_http_client_performance/
|
6
4
|
# Net::HTTP is the default adapter
|
7
5
|
|
8
|
-
# Each
|
6
|
+
# Each adapters response should be a hash with the following keys:
|
9
7
|
# :status_code
|
10
8
|
# :url
|
11
9
|
# :body
|
@@ -6,24 +6,24 @@ class RSolr::HTTPClient::Adapter::Curb
|
|
6
6
|
include RSolr::HTTPClient::Util
|
7
7
|
|
8
8
|
attr :uri
|
9
|
-
attr :
|
9
|
+
attr :connection
|
10
10
|
|
11
11
|
def initialize(url)
|
12
12
|
@uri = URI.parse(url)
|
13
|
-
@
|
13
|
+
@connection = ::Curl::Easy.new
|
14
14
|
end
|
15
15
|
|
16
16
|
def get(path, params={})
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
17
|
+
@connection.url = _build_url(path, params)
|
18
|
+
@connection.multipart_form_post = false
|
19
|
+
@connection.perform
|
20
20
|
create_http_context(path, params)
|
21
21
|
end
|
22
22
|
|
23
23
|
def post(path, data, params={}, headers={})
|
24
|
-
@
|
25
|
-
@
|
26
|
-
@
|
24
|
+
@connection.url = _build_url(path, params)
|
25
|
+
@connection.headers = headers
|
26
|
+
@connection.http_post(data)
|
27
27
|
create_http_context(path, params, data, headers)
|
28
28
|
end
|
29
29
|
|
@@ -31,9 +31,9 @@ class RSolr::HTTPClient::Adapter::Curb
|
|
31
31
|
|
32
32
|
def create_http_context(path, params, data=nil, headers={})
|
33
33
|
{
|
34
|
-
:status_code=>@
|
35
|
-
:url=>@
|
36
|
-
:body=>@
|
34
|
+
:status_code=>@connection.response_code.to_i,
|
35
|
+
:url=>@connection.url,
|
36
|
+
:body=>@connection.body_str,
|
37
37
|
:path=>path,
|
38
38
|
:params=>params,
|
39
39
|
:data=>data,
|
@@ -45,7 +45,7 @@ class RSolr::HTTPClient::Adapter::Curb
|
|
45
45
|
url = @uri.scheme + '://' + @uri.host
|
46
46
|
url += ':' + @uri.port.to_s if @uri.port
|
47
47
|
url += @uri.path + path
|
48
|
-
build_url(url, params, @uri.query)
|
48
|
+
build_url(url, params, @uri.query) # build_url is coming from RSolr::HTTPClient::Util
|
49
49
|
end
|
50
50
|
|
51
51
|
end
|
@@ -5,22 +5,22 @@ class RSolr::HTTPClient::Adapter::NetHTTP
|
|
5
5
|
include RSolr::HTTPClient::Util
|
6
6
|
|
7
7
|
attr :uri
|
8
|
-
attr :
|
8
|
+
attr :connection
|
9
9
|
|
10
10
|
def initialize(url)
|
11
11
|
@uri = URI.parse(url)
|
12
|
-
@
|
12
|
+
@connection = Net::HTTP.new(@uri.host, @uri.port)
|
13
13
|
end
|
14
14
|
|
15
15
|
def get(path, params={})
|
16
16
|
url = _build_url(path, params)
|
17
|
-
net_http_response = @
|
17
|
+
net_http_response = @connection.get(url)
|
18
18
|
create_http_context(net_http_response, url, path, params)
|
19
19
|
end
|
20
20
|
|
21
21
|
def post(path, data, params={}, headers={})
|
22
22
|
url = _build_url(path, params)
|
23
|
-
net_http_response = @
|
23
|
+
net_http_response = @connection.post(url, data, headers)
|
24
24
|
create_http_context(net_http_response, url, path, params, data, headers)
|
25
25
|
end
|
26
26
|
|
@@ -42,7 +42,7 @@ class RSolr::HTTPClient::Adapter::NetHTTP
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def _build_url(path, params={})
|
45
|
-
build_url(@uri.path + path, params, @uri.query)
|
45
|
+
build_url(@uri.path + path, params, @uri.query) # build_url is coming from RSolr::HTTPClient::Util
|
46
46
|
end
|
47
47
|
|
48
48
|
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.6.
|
4
|
+
version: 0.6.2
|
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-01-
|
12
|
+
date: 2009-01-14 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -49,8 +49,6 @@ files:
|
|
49
49
|
- lib/rsolr/http_client/adapter.rb
|
50
50
|
- lib/rsolr/http_client.rb
|
51
51
|
- lib/rsolr/indexer.rb
|
52
|
-
- lib/rsolr/mapper/rss.rb
|
53
|
-
- lib/rsolr/mapper.rb
|
54
52
|
- lib/rsolr/message.rb
|
55
53
|
- lib/rsolr/response/base.rb
|
56
54
|
- lib/rsolr/response/index_info.rb
|
@@ -98,7 +96,6 @@ test_files:
|
|
98
96
|
- test/http_client/test_methods.rb
|
99
97
|
- test/http_client/util_test.rb
|
100
98
|
- test/indexer.rb
|
101
|
-
- test/mapper_test.rb
|
102
99
|
- test/message_test.rb
|
103
100
|
- test/response/base_test.rb
|
104
101
|
- test/response/pagination_test.rb
|
data/lib/rsolr/indexer.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
class RSolr::Indexer
|
2
|
-
|
3
|
-
attr_reader :solr, :mapper, :opts
|
4
|
-
|
5
|
-
def initialize(solr, mapping_or_mapper, opts={})
|
6
|
-
@solr = solr
|
7
|
-
@mapper = mapping_or_mapper.is_a?(Hash) ? RSolr::Mapper::Base.new(mapping_or_mapper) : mapping_or_mapper
|
8
|
-
@opts = opts
|
9
|
-
end
|
10
|
-
|
11
|
-
# data - the raw data to send into the mapper
|
12
|
-
# params - url query params for solr /update handler
|
13
|
-
# commit - boolean; true==commit after adding, false==no commit after adding
|
14
|
-
# block can be used for modifying the "add", "doc" and "field" xml elements (for boosting etc.)
|
15
|
-
def index(data, params={}, &block)
|
16
|
-
docs = data.collect {|d| @mapper.map(d)}
|
17
|
-
@solr.add(docs, params) do |add, doc, field|
|
18
|
-
# check opts for :debug etc.?
|
19
|
-
yield add, doc, field if block_given?
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
data/lib/rsolr/mapper.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
module RSolr::Mapper
|
2
|
-
|
3
|
-
autoload :RSS, 'rsolr/mapper/rss'
|
4
|
-
|
5
|
-
class UnkownMappingValue < RuntimeError; end
|
6
|
-
|
7
|
-
class Base
|
8
|
-
|
9
|
-
attr_reader :mapping, :opts
|
10
|
-
|
11
|
-
def initialize(mapping={}, opts={}, &block)
|
12
|
-
@mapping = mapping
|
13
|
-
@opts = opts
|
14
|
-
yield @mapping if block_given?
|
15
|
-
end
|
16
|
-
|
17
|
-
# source - a hash or array of source data
|
18
|
-
# override_mapping - an alternate mapper
|
19
|
-
# returns an array with one or more mapped hashes
|
20
|
-
def map(source, override_mapping=nil, &block)
|
21
|
-
source = [source] if source.is_a?(Hash)
|
22
|
-
mapping = override_mapping || @mapping
|
23
|
-
index = -1
|
24
|
-
# collect a bunch of hashes...
|
25
|
-
source.collect do |src|
|
26
|
-
index += 1
|
27
|
-
# for each mapping item, inject data into a new hash
|
28
|
-
final_hash = mapping.inject({}) do |a_new_hash, (map_key, map_value)|
|
29
|
-
value = mapped_field_value(src, map_value, index)
|
30
|
-
value.to_s.empty? ? a_new_hash : a_new_hash.merge!({map_key=>value})
|
31
|
-
end
|
32
|
-
yield final_hash if block_given?
|
33
|
-
final_hash
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
protected
|
38
|
-
|
39
|
-
# This is a hook method useful for subclassing
|
40
|
-
def source_field_value(source, field_name, index)
|
41
|
-
source[field_name]
|
42
|
-
end
|
43
|
-
|
44
|
-
def mapped_field_value(source, mapped_value, index)
|
45
|
-
case mapped_value
|
46
|
-
when String
|
47
|
-
mapped_value
|
48
|
-
when Symbol
|
49
|
-
source_field_value(source, mapped_value, index)
|
50
|
-
when Proc
|
51
|
-
mapped_value.call(source, index)
|
52
|
-
when Enumerable
|
53
|
-
mapped_value.collect {|key| source_field_value(source, key, index)}.flatten
|
54
|
-
else
|
55
|
-
# try to turn it into a string, else raise UnkownMappingValue
|
56
|
-
mapped_value.respond_to?(:to_s) ? mapped_value.to_s : raise(UnkownMappingValue.new(mapped_value))
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
data/lib/rsolr/mapper/rss.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#TODO - this could use the http wrapper stuff instead of open-uri/net::http
|
2
|
-
|
3
|
-
require 'rss'
|
4
|
-
require 'open-uri'
|
5
|
-
|
6
|
-
class RSolr::Mapper::RSS < RSolr::Mapper::Base
|
7
|
-
|
8
|
-
attr_reader :rss
|
9
|
-
|
10
|
-
# rss_file_or_url is file path or url (see open-uri)
|
11
|
-
# override_mapping is an alternate mapping (see Solr::Mapper::Base)
|
12
|
-
# returns array of mapped hashes
|
13
|
-
def map(rss_file_or_url, override_mapping=nil)
|
14
|
-
open(rss_file_or_url) do |feed|
|
15
|
-
@rss = RSS::Parser.parse(feed.read, false)
|
16
|
-
super(rss.items.collect, override_mapping)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# sends methods chain down into the @rss object
|
21
|
-
# example: :'channel.title' == @rss.channel.title
|
22
|
-
# if the method chain doesn't exist, the super #source_field_value method is called
|
23
|
-
def source_field_value(source, method_path, index)
|
24
|
-
method_path.to_s.split('.').inject(@rss) do |rss, m|
|
25
|
-
rss.respond_to?(m) ? rss.send(m.to_sym) : super(source, method_path, index)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
data/test/mapper_test.rb
DELETED
@@ -1,123 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'test_helpers')
|
2
|
-
|
3
|
-
require 'rss'
|
4
|
-
|
5
|
-
class MapperTest < RSolrBaseTest
|
6
|
-
|
7
|
-
# simple replacement
|
8
|
-
def test_string_map
|
9
|
-
data = {
|
10
|
-
:skip_this=>'!'
|
11
|
-
}
|
12
|
-
mapping = {
|
13
|
-
:id=>'one',
|
14
|
-
:name=>'foo'
|
15
|
-
}
|
16
|
-
mapper = RSolr::Mapper::Base.new(mapping)
|
17
|
-
expected = [mapping]
|
18
|
-
assert_equal expected, mapper.map(data)
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_map_yields_if_block_given
|
22
|
-
data = {
|
23
|
-
:NUMID=>100,
|
24
|
-
:type=>:type_val,
|
25
|
-
:code=>:code_val
|
26
|
-
}
|
27
|
-
mapping = {
|
28
|
-
:id=>:NUMID,
|
29
|
-
:name=>'foo',
|
30
|
-
:category=>[:type, :code]
|
31
|
-
}
|
32
|
-
mapper = RSolr::Mapper::Base.new(mapping)
|
33
|
-
expected = [{:name=>"foo", :category=>[:type_val, :code_val], :id=>100}]
|
34
|
-
result = mapper.map(data) do |doc|
|
35
|
-
assert expected, doc
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# test enumerable/array mappings
|
40
|
-
def test_array_multi_value
|
41
|
-
data = {
|
42
|
-
:NUMID=>100,
|
43
|
-
:type=>:type_val,
|
44
|
-
:code=>:code_val
|
45
|
-
}
|
46
|
-
mapping = {
|
47
|
-
:id=>:NUMID,
|
48
|
-
:name=>'foo',
|
49
|
-
:category=>[:type, :code]
|
50
|
-
}
|
51
|
-
mapper = RSolr::Mapper::Base.new(mapping)
|
52
|
-
expected = [{:name=>"foo", :category=>[:type_val, :code_val], :id=>100}]
|
53
|
-
assert_equal expected, mapper.map(data)
|
54
|
-
end
|
55
|
-
|
56
|
-
# test the proc mapping type
|
57
|
-
# test that the second arg in the block is a Solr::Mapper
|
58
|
-
def test_proc
|
59
|
-
data = [{:name=>'-bach;'}]
|
60
|
-
mapping = {
|
61
|
-
:name=>proc{|d,index|
|
62
|
-
assert_equal Fixnum, index.class
|
63
|
-
d[:name].gsub(/\W+/, '')
|
64
|
-
}
|
65
|
-
}
|
66
|
-
mapper = RSolr::Mapper::Base.new(mapping)
|
67
|
-
expected = [{:name=>"bach"}]
|
68
|
-
assert_equal expected, mapper.map(data)
|
69
|
-
end
|
70
|
-
|
71
|
-
def rss_file
|
72
|
-
@rss_file ||= File.join(File.dirname(__FILE__), 'ruby-lang.org.rss.xml')
|
73
|
-
end
|
74
|
-
|
75
|
-
# load an rss feed
|
76
|
-
# create a mapping
|
77
|
-
# map it and test the fields
|
78
|
-
def raw_mapping_rss_docs
|
79
|
-
rss = RSS::Parser.parse(File.read(rss_file), false)
|
80
|
-
mapping = {
|
81
|
-
:channel=>rss.channel.title,
|
82
|
-
:url=>rss.channel.link,
|
83
|
-
:total=>rss.items.size,
|
84
|
-
:title=>proc {|item,index| item.title },
|
85
|
-
:link=>proc{|item,index| item.link },
|
86
|
-
:published=>proc{|item,index| item.date },
|
87
|
-
:description=>proc{|item,index| item.description }
|
88
|
-
}
|
89
|
-
mapper = RSolr::Mapper::Base.new(mapping)
|
90
|
-
mapper.map(rss.items)
|
91
|
-
end
|
92
|
-
|
93
|
-
# load an rss feed
|
94
|
-
# create a mapping
|
95
|
-
# map it and test the fields
|
96
|
-
def rss_mapper_docs
|
97
|
-
m = RSolr::Mapper::RSS.new
|
98
|
-
mapping = {
|
99
|
-
:channel=>:'channel.title',
|
100
|
-
:url=>:'channel.link',
|
101
|
-
:total=>:'items.size',
|
102
|
-
:title=>proc {|item,index| item.title },
|
103
|
-
:link=>proc {|item,index| item.link },
|
104
|
-
:published=>proc {|item,index| item.date },
|
105
|
-
:description=>proc {|item,index| item.description }
|
106
|
-
}
|
107
|
-
m.map(rss_file, mapping)
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_rss
|
111
|
-
[rss_mapper_docs, raw_mapping_rss_docs].each do |docs|
|
112
|
-
assert_equal 10, docs.size
|
113
|
-
first = docs.first
|
114
|
-
# make sure the mapped solr docs have all of the keys from the mapping
|
115
|
-
#assert mapping.keys.all?{|mapping_key| first.keys.include?(mapping_key) }
|
116
|
-
assert_equal docs.size, docs.first[:total].to_i
|
117
|
-
assert_equal Time.parse('Mon Nov 10 09:55:53 -0500 2008'), first[:published]
|
118
|
-
assert_equal 'http://www.ruby-lang.org/en/feeds/news.rss/', first[:url]
|
119
|
-
assert_equal 'Scotland on Rails 2009', first[:title]
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
end
|