mwmitchell-rsolr 0.6.1 → 0.6.2
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 +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
|