mwmitchell-solr 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +10 -15
- data/lib/solr.rb +1 -1
- data/lib/solr/connection/base.rb +5 -4
- data/lib/solr/connection/search_ext.rb +12 -0
- data/lib/solr/mapper.rb +13 -9
- data/lib/solr/mapper/rss.rb +2 -2
- data/lib/solr/message.rb +1 -1
- data/lib/solr/response/query.rb +80 -6
- data/test/connection/search_ext_test_methods.rb +17 -0
- data/test/mapper_test.rb +15 -10
- data/test/pagination_test.rb +1 -1
- metadata +8 -4
data/CHANGES.txt
CHANGED
@@ -1,27 +1,28 @@
|
|
1
|
+
0.5.6 - December 30, 2008
|
2
|
+
solr.gemspec cleanedup thanks to shairontoledo on github! :)
|
3
|
+
Added Solr::Response::Query::Facet module with helpers from the delsolr project
|
4
|
+
Also added test stub in test/connection/search_ext_test_methods.rb
|
5
|
+
Fixed pagination math errors
|
6
|
+
Added new SearchExt helper field: :phrase_filters
|
7
|
+
This will add quoted values to the :filters (fq solr param) hash for doing easier facet requests
|
8
|
+
|
9
|
+
Be sure to check out the new demo app: http://github.com/mwmitchell/consuminator/tree/master
|
10
|
+
|
1
11
|
0.5.5 - December 29, 2008
|
2
|
-
|
3
12
|
Fixed bug where accessing a field by method name failed:
|
4
|
-
|
5
13
|
docs.each do |doc|
|
6
14
|
doc.timestamp
|
7
15
|
end
|
8
|
-
|
9
16
|
Fixed bug where using the #has? method on a doc failed:
|
10
|
-
|
11
17
|
docs.each do |doc|
|
12
18
|
doc.has?('timestamp')
|
13
19
|
end
|
14
|
-
|
15
20
|
Removed invalid autoload in Solr module
|
16
|
-
|
17
21
|
Fixed spelling error in Solr::Connection::SearchExt (thanks to matthewrudy)
|
18
22
|
|
19
23
|
0.5.4 - December 29, 2008
|
20
|
-
|
21
24
|
Re-organized the main Solr adapters, they're now in Solr::Connection::Adapter instead of Solr::Adapter
|
22
|
-
|
23
25
|
All responses from HTTPClient and Connection::Adapter::Direct return a hash with the following keys:
|
24
|
-
|
25
26
|
:status_code
|
26
27
|
:body
|
27
28
|
:params
|
@@ -29,18 +30,12 @@
|
|
29
30
|
:path
|
30
31
|
:headers
|
31
32
|
:data
|
32
|
-
|
33
33
|
This hash is now available in the solr response objects as #source - this will be useful in testing and debugging by allowing you to see the generated params and queries... example:
|
34
|
-
|
35
34
|
response = Solr.query(:q=>'*:*')
|
36
35
|
response.source[:params]
|
37
36
|
response.source[:body]
|
38
37
|
response.source[:url]
|
39
|
-
|
40
38
|
Added MultiValue field support in Solr::Message, thanks to Fouad Mardini
|
41
|
-
|
42
39
|
Bug in Solr::Connection::SearchExt where the :q params was not getting generated - fixed by Fouad Mardini
|
43
|
-
|
44
40
|
Organized tests a bit, moved connection tests into test/connection
|
45
|
-
|
46
41
|
Fixed a bug in Solr::Connection::Adapter::HTTP where invalid HTTP POST headers were being generated
|
data/lib/solr.rb
CHANGED
data/lib/solr/connection/base.rb
CHANGED
@@ -103,10 +103,11 @@ class Solr::Connection::Base
|
|
103
103
|
Solr::Message
|
104
104
|
end
|
105
105
|
|
106
|
-
def modify_params_for_pagination(
|
107
|
-
return
|
108
|
-
params =
|
109
|
-
params[:
|
106
|
+
def modify_params_for_pagination(orig_params)
|
107
|
+
return orig_params unless orig_params[:page] || orig_params[:per_page]
|
108
|
+
params = orig_params.dup # be nice
|
109
|
+
params[:page] ||= 1
|
110
|
+
params[:per_page] ||= 10
|
110
111
|
params[:rows] = params.delete(:per_page).to_i
|
111
112
|
params[:start] = calculate_start(params.delete(:page).to_i, params[:rows])
|
112
113
|
params
|
@@ -6,6 +6,18 @@ module Solr::Connection::SearchExt
|
|
6
6
|
params[:fl] = fields.is_a?(Array) ? fields.join(' ') : fields
|
7
7
|
end
|
8
8
|
|
9
|
+
# adds quoted values to the :filters hash
|
10
|
+
if params[:phrase_filters]
|
11
|
+
phrase_filters = params.delete(:phrase_filters)
|
12
|
+
params[:filters] ||= {}
|
13
|
+
phrase_filters.each do |filter,values|
|
14
|
+
params[:filters][filter] ||= []
|
15
|
+
values.each do |v|
|
16
|
+
params[:filters][filter] << "\"#{v}\""
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
9
21
|
params[:fq] = build_filters(params.delete(:filters)) if params[:filters]
|
10
22
|
facets = params.delete(:facets) if params[:facets]
|
11
23
|
|
data/lib/solr/mapper.rb
CHANGED
@@ -19,11 +19,15 @@ module Solr::Mapper
|
|
19
19
|
# returns an array with one or more mapped hashes
|
20
20
|
def map(source, override_mapping=nil)
|
21
21
|
source = [source] if source.is_a?(Hash)
|
22
|
-
|
22
|
+
mapping = override_mapping || @mapping
|
23
|
+
index = -1
|
24
|
+
# collect a bunch of hashes...
|
23
25
|
source.collect do |src|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
index += 1
|
27
|
+
# for each mapping item, inject data into a new hash
|
28
|
+
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})
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
@@ -31,20 +35,20 @@ module Solr::Mapper
|
|
31
35
|
protected
|
32
36
|
|
33
37
|
# This is a hook method useful for subclassing
|
34
|
-
def source_field_value(source, field_name)
|
38
|
+
def source_field_value(source, field_name, index)
|
35
39
|
source[field_name]
|
36
40
|
end
|
37
41
|
|
38
|
-
def mapped_field_value(source, mapped_value)
|
42
|
+
def mapped_field_value(source, mapped_value, index)
|
39
43
|
case mapped_value
|
40
44
|
when String
|
41
45
|
mapped_value
|
42
46
|
when Symbol
|
43
|
-
source_field_value(source, mapped_value)
|
47
|
+
source_field_value(source, mapped_value, index)
|
44
48
|
when Proc
|
45
|
-
mapped_value.call(source,
|
49
|
+
mapped_value.call(source, index)
|
46
50
|
when Enumerable
|
47
|
-
mapped_value.collect {|key| source_field_value(source, key)}.flatten
|
51
|
+
mapped_value.collect {|key| source_field_value(source, key, index)}.flatten
|
48
52
|
else
|
49
53
|
# try to turn it into a string, else raise UnkownMappingValue
|
50
54
|
mapped_value.respond_to?(:to_s) ? mapped_value.to_s : raise(UnkownMappingValue.new(mapped_value))
|
data/lib/solr/mapper/rss.rb
CHANGED
@@ -20,9 +20,9 @@ class Solr::Mapper::RSS < Solr::Mapper::Base
|
|
20
20
|
# sends methods chain down into the @rss object
|
21
21
|
# example: :'channel.title' == @rss.channel.title
|
22
22
|
# if the method chain doesn't exist, the super #source_field_value method is called
|
23
|
-
def source_field_value(source, method_path)
|
23
|
+
def source_field_value(source, method_path, index)
|
24
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)
|
25
|
+
rss.respond_to?(m) ? rss.send(m.to_sym) : super(source, method_path, index)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
data/lib/solr/message.rb
CHANGED
@@ -28,7 +28,7 @@ class Solr::Message
|
|
28
28
|
sorted_items = item.inject({}) {|acc,(k,v)| acc.merge({k.to_s=>v})}
|
29
29
|
sorted_items.keys.sort.each do |k|
|
30
30
|
doc_attrs = {:name=>k}
|
31
|
-
yield doc_attrs if block_given?
|
31
|
+
yield item, doc_attrs if block_given?
|
32
32
|
[sorted_items[k]].flatten.each do |v| # multiValued attributes
|
33
33
|
doc_xml.field(v, doc_attrs)
|
34
34
|
end
|
data/lib/solr/response/query.rb
CHANGED
@@ -33,36 +33,109 @@ module Solr::Response::Query
|
|
33
33
|
|
34
34
|
end
|
35
35
|
|
36
|
+
# from the delsolr project -> http://github.com/avvo/delsolr/tree/master/lib/delsolr/response.rb
|
37
|
+
module Facets
|
38
|
+
|
39
|
+
def facets
|
40
|
+
@facets ||= data['facet_counts'] || {}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the hash of all the facet_fields (ie: {'instock_b' => ['true', 123, 'false', 20]}
|
44
|
+
def facet_fields
|
45
|
+
@facet_fields ||= facets['facet_fields'] || {}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns all of the facet queries
|
49
|
+
def facet_queries
|
50
|
+
@facet_queries ||= facets['facet_queries'] || {}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns a hash of hashs rather than a hash of arrays (ie: {'instock_b' => {'true' => 123', 'false', => 20} })
|
54
|
+
def facet_fields_by_hash
|
55
|
+
@facet_fields_by_hash ||= begin
|
56
|
+
f = {}
|
57
|
+
if facet_fields
|
58
|
+
facet_fields.each do |field,value_and_counts|
|
59
|
+
f[field] = {}
|
60
|
+
value_and_counts.each_with_index do |v, i|
|
61
|
+
if i % 2 == 0
|
62
|
+
f[field][v] = value_and_counts[i+1]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
f
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns an array of value/counts for a given field (ie: ['true', 123, 'false', 20]
|
72
|
+
def facet_field(field)
|
73
|
+
facet_fields[field.to_s]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the array of field values for the given field in the order they were returned from solr
|
77
|
+
def facet_field_values(field)
|
78
|
+
facet_field_values ||= {}
|
79
|
+
facet_field_values[field.to_s] ||= begin
|
80
|
+
a = []
|
81
|
+
return unless facet_field(field)
|
82
|
+
facet_field(field).each_with_index do |val_or_count, i|
|
83
|
+
a << val_or_count if i % 2 == 0 && facet_field(field)[i+1] > 0
|
84
|
+
end
|
85
|
+
a
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns a hash of value/counts for a given field (ie: {'true' => 123, 'false' => 20}
|
90
|
+
def facet_field_by_hash(field)
|
91
|
+
facet_fields_by_hash[field.to_s]
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns the count for the given field/value pair
|
95
|
+
def facet_field_count(field, value)
|
96
|
+
facet_fields_by_hash[field.to_s][value.to_s] if facet_fields_by_hash[field.to_s]
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the counts for a given facet_query_name
|
100
|
+
def facet_query_count_by_name(facet_query_name)
|
101
|
+
query_string = query_builder.facet_query_by_name(facet_query_name)
|
102
|
+
facet_queries[query_string] if query_string
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
#
|
109
|
+
#
|
36
110
|
module Pagination
|
37
111
|
|
38
112
|
# alias to the Solr param, 'rows'
|
39
113
|
def per_page
|
40
|
-
@per_page
|
114
|
+
@per_page ||= params['rows'].to_s.to_i
|
41
115
|
end
|
42
116
|
|
43
117
|
# Returns the current page calculated from 'rows' and 'start'
|
44
118
|
# WillPaginate hook
|
45
119
|
def current_page
|
46
|
-
@current_page
|
47
|
-
@current_page == 0 ? 1 : @current_page
|
120
|
+
@current_page ||= (self.start / self.per_page).ceil + 1
|
48
121
|
end
|
49
122
|
|
50
123
|
# Calcuates the total pages from 'numFound' and 'rows'
|
51
124
|
# WillPaginate hook
|
52
125
|
def total_pages
|
53
|
-
self.per_page > 0 ? (self.total / self.per_page.to_f).ceil : 1
|
126
|
+
@total_pages ||= self.per_page > 0 ? (self.total / self.per_page.to_f).ceil : 1
|
54
127
|
end
|
55
128
|
|
56
129
|
# returns the previous page number or 1
|
57
130
|
# WillPaginate hook
|
58
131
|
def previous_page
|
59
|
-
(current_page > 1) ? current_page - 1 : 1
|
132
|
+
@previous_page ||= (current_page > 1) ? current_page - 1 : 1
|
60
133
|
end
|
61
134
|
|
62
135
|
# returns the next page number or the last
|
63
136
|
# WillPaginate hook
|
64
137
|
def next_page
|
65
|
-
(current_page < total_pages) ? current_page + 1 : total_pages
|
138
|
+
@next_page ||= (current_page < total_pages) ? current_page + 1 : total_pages
|
66
139
|
end
|
67
140
|
|
68
141
|
end
|
@@ -74,6 +147,7 @@ module Solr::Response::Query
|
|
74
147
|
class Base < Solr::Response::Base
|
75
148
|
|
76
149
|
include Solr::Response::Query::Pagination
|
150
|
+
include Solr::Response::Query::Facets
|
77
151
|
|
78
152
|
attr_reader :response, :docs, :num_found, :start
|
79
153
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
raise 'Not yet implemented!'
|
2
|
+
|
3
|
+
module SearchExtTestMethods
|
4
|
+
|
5
|
+
def test_facet_response_methods
|
6
|
+
@response.facets
|
7
|
+
@response.facet_fields
|
8
|
+
@response.facet_queries
|
9
|
+
@response.facet_fields_by_hash
|
10
|
+
@response.facet_field(:feed_language_facet)
|
11
|
+
@response.facet_field_values(:feed_language_facet)
|
12
|
+
@response.facet_field_by_hash(:feed_language_facet)
|
13
|
+
@response.facet_field_by_hash(:feed_language_facet)
|
14
|
+
@response.facet_field_count(:feed_title_facet, 'ScienceDaily: Latest Science News')
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/test/mapper_test.rb
CHANGED
@@ -18,6 +18,11 @@ class MapperTest < Test::Unit::TestCase
|
|
18
18
|
assert_equal expected, mapper.map(data)
|
19
19
|
end
|
20
20
|
|
21
|
+
# TODO
|
22
|
+
def test_add_and_set_doc_attributes
|
23
|
+
assert false
|
24
|
+
end
|
25
|
+
|
21
26
|
# test enumerable/array mappings
|
22
27
|
def test_array_multi_value
|
23
28
|
data = {
|
@@ -40,8 +45,8 @@ class MapperTest < Test::Unit::TestCase
|
|
40
45
|
def test_proc
|
41
46
|
data = [{:name=>'-bach;'}]
|
42
47
|
mapping = {
|
43
|
-
:name=>proc{|d,
|
44
|
-
assert_equal
|
48
|
+
:name=>proc{|d,index|
|
49
|
+
assert_equal Fixnum, index.class
|
45
50
|
d[:name].gsub(/\W+/, '')
|
46
51
|
}
|
47
52
|
}
|
@@ -63,10 +68,10 @@ class MapperTest < Test::Unit::TestCase
|
|
63
68
|
:channel=>rss.channel.title,
|
64
69
|
:url=>rss.channel.link,
|
65
70
|
:total=>rss.items.size,
|
66
|
-
:title=>proc {|item,
|
67
|
-
:link=>proc{|item,
|
68
|
-
:published=>proc{|item,
|
69
|
-
:description=>proc{|item,
|
71
|
+
:title=>proc {|item,index| item.title },
|
72
|
+
:link=>proc{|item,index| item.link },
|
73
|
+
:published=>proc{|item,index| item.date },
|
74
|
+
:description=>proc{|item,index| item.description }
|
70
75
|
}
|
71
76
|
mapper = Solr::Mapper::Base.new(mapping)
|
72
77
|
mapper.map(rss.items)
|
@@ -81,10 +86,10 @@ class MapperTest < Test::Unit::TestCase
|
|
81
86
|
:channel=>:'channel.title',
|
82
87
|
:url=>:'channel.link',
|
83
88
|
:total=>:'items.size',
|
84
|
-
:title=>proc {|item,
|
85
|
-
:link=>proc {|item,
|
86
|
-
:published=>proc {|item,
|
87
|
-
:description=>proc {|item,
|
89
|
+
:title=>proc {|item,index| item.title },
|
90
|
+
:link=>proc {|item,index| item.link },
|
91
|
+
:published=>proc {|item,index| item.date },
|
92
|
+
:description=>proc {|item,index| item.description }
|
88
93
|
}
|
89
94
|
m.map(rss_file, mapping)
|
90
95
|
end
|
data/test/pagination_test.rb
CHANGED
@@ -51,7 +51,7 @@ class PaginationTest < Test::Unit::TestCase
|
|
51
51
|
assert_equal response.params['rows'], response.per_page
|
52
52
|
assert_equal 26, response.total
|
53
53
|
# 2 per page, currently on the 10th item
|
54
|
-
assert_equal
|
54
|
+
assert_equal 2, response.current_page
|
55
55
|
assert_equal 9, response.total_pages
|
56
56
|
end
|
57
57
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mwmitchell-solr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
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: 2008-12-
|
12
|
+
date: 2008-12-30 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -27,8 +27,11 @@ executables: []
|
|
27
27
|
|
28
28
|
extensions: []
|
29
29
|
|
30
|
-
extra_rdoc_files:
|
31
|
-
|
30
|
+
extra_rdoc_files:
|
31
|
+
- LICENSE
|
32
|
+
- Rakefile
|
33
|
+
- README.rdoc
|
34
|
+
- CHANGES.txt
|
32
35
|
files:
|
33
36
|
- examples/http.rb
|
34
37
|
- examples/direct.rb
|
@@ -89,6 +92,7 @@ test_files:
|
|
89
92
|
- test/connection/direct_test.rb
|
90
93
|
- test/connection/http_test.rb
|
91
94
|
- test/connection/test_methods.rb
|
95
|
+
- test/connection/search_ext_test_methods.rb
|
92
96
|
- test/core_ext_test
|
93
97
|
- test/http_client/curb_test.rb
|
94
98
|
- test/http_client/net_http_test.rb
|