gsolr_ext 0.12.3
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/.gitignore +3 -0
- data/LICENSE +13 -0
- data/README.rdoc +126 -0
- data/Rakefile +46 -0
- data/TODO.txt +1 -0
- data/VERSION +1 -0
- data/gsolr_ext.gemspec +32 -0
- data/gsolr_ext.tmproj +258 -0
- data/lib/gsolr_ext.rb +42 -0
- data/lib/gsolr_ext/client.rb +65 -0
- data/lib/gsolr_ext/doc.rb +44 -0
- data/lib/gsolr_ext/model.rb +111 -0
- data/lib/gsolr_ext/request.rb +110 -0
- data/lib/gsolr_ext/response.rb +65 -0
- data/lib/gsolr_ext/response/docs.rb +56 -0
- data/lib/gsolr_ext/response/facets.rb +58 -0
- data/lib/gsolr_ext/response/spelling.rb +92 -0
- data/lib/mash.rb +143 -0
- data/spec/gsolr_ext_spec.rb +276 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +32 -0
- metadata +111 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
module GSolr::Ext::Response::Facets
|
2
|
+
|
3
|
+
# represents a facet value; which is a field value and its hit count
|
4
|
+
class FacetItem
|
5
|
+
attr_reader :value, :hits
|
6
|
+
def initialize value, hits
|
7
|
+
@value, @hits = value, hits
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# represents a facet; which is a field and its values
|
12
|
+
class FacetField
|
13
|
+
attr_reader :name, :items
|
14
|
+
def initialize name, items
|
15
|
+
@name, @items = name, items
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @response.facets.each do |facet|
|
20
|
+
# facet.name
|
21
|
+
# facet.items
|
22
|
+
# end
|
23
|
+
# "caches" the result in the @facets instance var
|
24
|
+
def facets
|
25
|
+
@facets ||= (
|
26
|
+
facet_fields.map do |(facet_field_name,values_and_hits)|
|
27
|
+
items = []
|
28
|
+
(values_and_hits.size/2).times do |index|
|
29
|
+
items << FacetItem.new(values_and_hits[index*2], values_and_hits[index*2+1])
|
30
|
+
end
|
31
|
+
FacetField.new(facet_field_name, items)
|
32
|
+
end
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
# pass in a facet field name and get back a Facet instance
|
37
|
+
def facet_by_field_name(name)
|
38
|
+
@facets_by_field_name ||= {}
|
39
|
+
@facets_by_field_name[name] ||= (
|
40
|
+
facets.detect{|facet|facet.name.to_s == name.to_s}
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def facet_counts
|
45
|
+
@facet_counts ||= self['facet_counts'] || {}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the hash of all the facet_fields (ie: {'instock_b' => ['true', 123, 'false', 20]}
|
49
|
+
def facet_fields
|
50
|
+
@facet_fields ||= facet_counts['facet_fields'] || {}
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns all of the facet queries
|
54
|
+
def facet_queries
|
55
|
+
@facet_queries ||= facet_counts['facet_queries'] || {}
|
56
|
+
end
|
57
|
+
|
58
|
+
end # end Facets
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# A mixin for making access to the spellcheck component data easy.
|
2
|
+
#
|
3
|
+
# response.spelling.words
|
4
|
+
#
|
5
|
+
module GSolr::Ext::Response::Spelling
|
6
|
+
|
7
|
+
def spelling
|
8
|
+
@spelling ||= Base.new(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Base
|
12
|
+
|
13
|
+
attr :response
|
14
|
+
|
15
|
+
def initialize(response)
|
16
|
+
@response = response
|
17
|
+
end
|
18
|
+
|
19
|
+
# returns an array of spelling suggestion for specific query words,
|
20
|
+
# as provided in the solr response. Only includes words with higher
|
21
|
+
# frequency of occurrence than word in original query.
|
22
|
+
# can't do a full query suggestion because we only get info for each word;
|
23
|
+
# combination of words may not have results.
|
24
|
+
# Thanks to Naomi Dushay!
|
25
|
+
def words
|
26
|
+
@words ||= (
|
27
|
+
word_suggestions = []
|
28
|
+
spellcheck = self.response[:spellcheck]
|
29
|
+
if spellcheck && spellcheck[:suggestions]
|
30
|
+
suggestions = spellcheck[:suggestions]
|
31
|
+
unless suggestions.nil?
|
32
|
+
# suggestions is an array:
|
33
|
+
# (query term)
|
34
|
+
# (hash of term info and term suggestion)
|
35
|
+
# ...
|
36
|
+
# (query term)
|
37
|
+
# (hash of term info and term suggestion)
|
38
|
+
# 'correctlySpelled'
|
39
|
+
# true/false
|
40
|
+
# collation
|
41
|
+
# (suggestion for collation)
|
42
|
+
if suggestions.index("correctlySpelled") #if extended results
|
43
|
+
i_stop = suggestions.index("correctlySpelled")
|
44
|
+
elsif suggestions.index("collation")
|
45
|
+
i_stop = suggestions.index("collation")
|
46
|
+
else
|
47
|
+
i_stop = suggestions.length
|
48
|
+
end
|
49
|
+
# step through array in 2s to get info for each term
|
50
|
+
0.step(i_stop-1, 2) do |i|
|
51
|
+
term = suggestions[i]
|
52
|
+
term_info = suggestions[i+1]
|
53
|
+
# term_info is a hash:
|
54
|
+
# numFound =>
|
55
|
+
# startOffset =>
|
56
|
+
# endOffset =>
|
57
|
+
# origFreq =>
|
58
|
+
# suggestion => [{ frequency =>, word => }] # for extended results
|
59
|
+
# suggestion => ['word'] # for non-extended results
|
60
|
+
origFreq = term_info['origFreq']
|
61
|
+
if suggestions.index("correctlySpelled")
|
62
|
+
word_suggestions << term_info['suggestion'].map do |suggestion|
|
63
|
+
suggestion['word'] if suggestion['freq'] > origFreq
|
64
|
+
end
|
65
|
+
else
|
66
|
+
# only extended suggestions have frequency so we just return all suggestions
|
67
|
+
word_suggestions << term_info['suggestion']
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
word_suggestions.flatten.compact.uniq
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def collation
|
77
|
+
# FIXME: DRY up with words
|
78
|
+
spellcheck = self.response[:spellcheck]
|
79
|
+
if spellcheck && spellcheck[:suggestions]
|
80
|
+
suggestions = spellcheck[:suggestions]
|
81
|
+
unless suggestions.nil?
|
82
|
+
if suggestions.index("collation")
|
83
|
+
suggestions[suggestions.index("collation") + 1]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
data/lib/mash.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# This class has dubious semantics and we only have it so that people can write
|
2
|
+
# params[:key] instead of params['key'].
|
3
|
+
class Mash < Hash
|
4
|
+
|
5
|
+
# @param constructor<Object>
|
6
|
+
# The default value for the mash. Defaults to an empty hash.
|
7
|
+
#
|
8
|
+
# @details [Alternatives]
|
9
|
+
# If constructor is a Hash, a new mash will be created based on the keys of
|
10
|
+
# the hash and no default value will be set.
|
11
|
+
def initialize(constructor = {})
|
12
|
+
if constructor.is_a?(Hash)
|
13
|
+
super()
|
14
|
+
update(constructor)
|
15
|
+
else
|
16
|
+
super(constructor)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param key<Object> The default value for the mash. Defaults to nil.
|
21
|
+
#
|
22
|
+
# @details [Alternatives]
|
23
|
+
# If key is a Symbol and it is a key in the mash, then the default value will
|
24
|
+
# be set to the value matching the key.
|
25
|
+
def default(key = nil)
|
26
|
+
if key.is_a?(Symbol) && include?(key = key.to_s)
|
27
|
+
self[key]
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
34
|
+
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
35
|
+
|
36
|
+
# @param key<Object> The key to set.
|
37
|
+
# @param value<Object>
|
38
|
+
# The value to set the key to.
|
39
|
+
#
|
40
|
+
# @see Mash#convert_key
|
41
|
+
# @see Mash#convert_value
|
42
|
+
def []=(key, value)
|
43
|
+
regular_writer(convert_key(key), convert_value(value))
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param other_hash<Hash>
|
47
|
+
# A hash to update values in the mash with. The keys and the values will be
|
48
|
+
# converted to Mash format.
|
49
|
+
#
|
50
|
+
# @return <Mash> The updated mash.
|
51
|
+
def update(other_hash)
|
52
|
+
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_method :merge!, :update
|
57
|
+
|
58
|
+
# @param key<Object> The key to check for. This will be run through convert_key.
|
59
|
+
#
|
60
|
+
# @return <TrueClass, FalseClass> True if the key exists in the mash.
|
61
|
+
def key?(key)
|
62
|
+
super(convert_key(key))
|
63
|
+
end
|
64
|
+
|
65
|
+
# def include? def has_key? def member?
|
66
|
+
alias_method :include?, :key?
|
67
|
+
alias_method :has_key?, :key?
|
68
|
+
alias_method :member?, :key?
|
69
|
+
|
70
|
+
# @param key<Object> The key to fetch. This will be run through convert_key.
|
71
|
+
# @param *extras<Array> Default value.
|
72
|
+
#
|
73
|
+
# @return <Object> The value at key or the default value.
|
74
|
+
def fetch(key, *extras)
|
75
|
+
super(convert_key(key), *extras)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param *indices<Array>
|
79
|
+
# The keys to retrieve values for. These will be run through +convert_key+.
|
80
|
+
#
|
81
|
+
# @return <Array> The values at each of the provided keys
|
82
|
+
def values_at(*indices)
|
83
|
+
indices.collect {|key| self[convert_key(key)]}
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return <Mash> A duplicate of this mash.
|
87
|
+
def dup
|
88
|
+
Mash.new(self)
|
89
|
+
end
|
90
|
+
|
91
|
+
# @param hash<Hash> The hash to merge with the mash.
|
92
|
+
#
|
93
|
+
# @return <Mash> A new mash with the hash values merged in.
|
94
|
+
def merge(hash)
|
95
|
+
self.dup.update(hash)
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param key<Object>
|
99
|
+
# The key to delete from the mash.\
|
100
|
+
def delete(key)
|
101
|
+
super(convert_key(key))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Used to provide the same interface as Hash.
|
105
|
+
#
|
106
|
+
# @return <Mash> This mash unchanged.
|
107
|
+
def stringify_keys!; self end
|
108
|
+
|
109
|
+
# @return <Hash> The mash as a Hash with string keys.
|
110
|
+
def to_hash
|
111
|
+
Hash.new(default).merge(self)
|
112
|
+
end
|
113
|
+
|
114
|
+
protected
|
115
|
+
# @param key<Object> The key to convert.
|
116
|
+
#
|
117
|
+
# @param <Object>
|
118
|
+
# The converted key. If the key was a symbol, it will be converted to a
|
119
|
+
# string.
|
120
|
+
#
|
121
|
+
# @api private
|
122
|
+
def convert_key(key)
|
123
|
+
key.kind_of?(Symbol) ? key.to_s : key
|
124
|
+
end
|
125
|
+
|
126
|
+
# @param value<Object> The value to convert.
|
127
|
+
#
|
128
|
+
# @return <Object>
|
129
|
+
# The converted value. A Hash or an Array of hashes, will be converted to
|
130
|
+
# their Mash equivalents.
|
131
|
+
#
|
132
|
+
# @api private
|
133
|
+
def convert_value(value)
|
134
|
+
case value
|
135
|
+
when Hash
|
136
|
+
value.to_mash
|
137
|
+
when Array
|
138
|
+
value.collect { |e| convert_value(e) }
|
139
|
+
else
|
140
|
+
value
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe GSolr::Ext do
|
4
|
+
|
5
|
+
context GSolr::Client do
|
6
|
+
|
7
|
+
let(:client){GSolr.connect}
|
8
|
+
|
9
|
+
it 'should now have a #find method' do
|
10
|
+
client.should respond_to(:find)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should produce results from the #find method' do
|
14
|
+
c = client
|
15
|
+
c.should_receive(:request).
|
16
|
+
with('/select', {:rows=>10, :start=>20, :q=>"*:*"}).
|
17
|
+
and_return({'response'=>{'docs' => []}, 'responseHeader' => {}})
|
18
|
+
response = c.find :page=>3, :per_page=>10, :q=>'*:*'#, :page=>1, :per_page=>10
|
19
|
+
response.should be_a(Mash)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should call the #find method with a custom request handler' do
|
23
|
+
c = client
|
24
|
+
expected_response = {'response'=>{'docs' => []}, 'responseHeader' => {}}
|
25
|
+
# ok this is hacky... the raw method needs to go into a mixin dude
|
26
|
+
def expected_response.raw
|
27
|
+
{:path => '/select'}
|
28
|
+
end
|
29
|
+
c.should_receive(:request).
|
30
|
+
with('/select', {:q=>'*:*'}).
|
31
|
+
and_return(expected_response)
|
32
|
+
response = c.find '/select', :q=>'*:*'
|
33
|
+
response.raw[:path].should match(/\/select/)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should be ok' do
|
37
|
+
c = client
|
38
|
+
c.should_receive(:request).
|
39
|
+
with('/select', :q=>'*:*').
|
40
|
+
and_return({'response'=>{'docs' => []}, 'responseHeader' => {'status'=>0}})
|
41
|
+
response = c.find :q=>'*:*'
|
42
|
+
response.should respond_to(:ok?)
|
43
|
+
response.ok?.should == true
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should call the #luke method' do
|
47
|
+
c = client
|
48
|
+
c.should_receive(:request).
|
49
|
+
with('/admin/luke', {"numTerms"=>0}).
|
50
|
+
and_return({"fields"=>nil, "index"=>nil, "info" => nil})
|
51
|
+
info = c.luke
|
52
|
+
info.should be_a(Mash)
|
53
|
+
info.should have_key('fields')
|
54
|
+
info.should have_key('index')
|
55
|
+
info.should have_key('info')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should forwad #ping? calls to the connection' do
|
59
|
+
client.connection.should_receive(:request).
|
60
|
+
with('/admin/ping', :wt => :ruby ).
|
61
|
+
and_return( :params => { :wt => :ruby },
|
62
|
+
:status_code => 200,
|
63
|
+
:body => "{'responseHeader'=>{'status'=>0,'QTime'=>44,'params'=>{'echoParams'=>'all','echoParams'=>'all','q'=>'solrpingquery','qt'=>'standard','wt'=>'ruby'}},'status'=>'OK'}" )
|
64
|
+
client.ping?
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should raise an error if the ping service is not available' do
|
68
|
+
client.connection.should_receive(:request).
|
69
|
+
with('/admin/ping', :wt => :ruby ).
|
70
|
+
# the first part of the what the message would really be
|
71
|
+
and_raise( GSolr::RequestError.new("Solr Response: pingQuery_not_configured_consider_registering_PingRequestHandler_with_the_name_adminping_instead__") )
|
72
|
+
lambda { client.ping? }.should raise_error( GSolr::RequestError )
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'requests' do
|
78
|
+
|
79
|
+
it 'should create a valid request' do
|
80
|
+
solr_params = GSolr::Ext::Request.map(
|
81
|
+
:page=>'2',
|
82
|
+
:per_page=>'10',
|
83
|
+
:phrases=>{:name=>'This is a phrase'},
|
84
|
+
:filters=>['test', {:price=>(1..10)}],
|
85
|
+
:phrase_filters=>{:manu=>['Apple']},
|
86
|
+
:queries=>'ipod',
|
87
|
+
:facets=>{:fields=>['cat', 'blah']},
|
88
|
+
:spellcheck => true
|
89
|
+
)
|
90
|
+
["test", "price:[1 TO 10]", "manu:\"Apple\""].should == solr_params[:fq]
|
91
|
+
solr_params[:start].should == 10
|
92
|
+
solr_params[:rows].should == 10
|
93
|
+
solr_params[:q].should == "ipod name:\"This is a phrase\""
|
94
|
+
solr_params['facet.field'].should == ['cat', 'blah']
|
95
|
+
solr_params[:facet].should == true
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should map fq using the phrase_filters mapping' do
|
99
|
+
solr_params = GSolr::Ext::Request.map(
|
100
|
+
:phrase_filters=>{:manu=>['Apple', 'ASG'], :color=>['red', 'blue']}
|
101
|
+
)
|
102
|
+
|
103
|
+
solr_params[:fq].size.should == 4
|
104
|
+
solr_params[:fq].should include("color:\"red\"")
|
105
|
+
solr_params[:fq].should include("color:\"blue\"")
|
106
|
+
solr_params[:fq].should include("manu:\"Apple\"")
|
107
|
+
solr_params[:fq].should include("manu:\"ASG\"")
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should map :filters and :phrase_filters while keeping an existing :fq' do
|
112
|
+
solr_params = GSolr::Ext::Request.map(
|
113
|
+
:fq => 'blah blah',
|
114
|
+
:phrase_filters=>{:manu=>['Apple', 'ASG'], :color=>['red', 'blue']}
|
115
|
+
)
|
116
|
+
|
117
|
+
solr_params[:fq].size.should == 5
|
118
|
+
solr_params[:fq].should include("blah blah")
|
119
|
+
solr_params[:fq].should include("color:\"red\"")
|
120
|
+
solr_params[:fq].should include("color:\"blue\"")
|
121
|
+
solr_params[:fq].should include("manu:\"Apple\"")
|
122
|
+
solr_params[:fq].should include("manu:\"ASG\"")
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should map arrays of ranges in :phrase_filters' do
|
126
|
+
solr_params = GSolr::Ext::Request.map(
|
127
|
+
:phrase_filters=>{:range=>[1940..2020]}
|
128
|
+
)
|
129
|
+
|
130
|
+
solr_params[:fq].size.should == 1
|
131
|
+
solr_params[:fq].should include("range:[1940 TO 2020]")
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'response' do
|
137
|
+
|
138
|
+
def create_response
|
139
|
+
raw_response = eval(mock_query_response)
|
140
|
+
GSolr::Ext::Response::Base.new(raw_response, '/select', raw_response['params'])
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should create a valid response' do
|
144
|
+
r = create_response
|
145
|
+
r.should respond_to(:header)
|
146
|
+
r.ok?.should == true
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should have accurate pagination numbers' do
|
150
|
+
r = create_response
|
151
|
+
r.rows.should == 11
|
152
|
+
r.total.should == 26
|
153
|
+
r.start.should == 0
|
154
|
+
r.docs.per_page.should == 11
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should create a valid response class' do
|
158
|
+
r = create_response
|
159
|
+
|
160
|
+
r.should respond_to(:response)
|
161
|
+
r.ok?.should == true
|
162
|
+
r.docs.size.should == 11
|
163
|
+
r.params[:echoParams].should == 'EXPLICIT'
|
164
|
+
r.docs.previous_page.should == 1
|
165
|
+
r.docs.next_page.should == 2
|
166
|
+
#
|
167
|
+
r.should be_a(GSolr::Ext::Response::Docs)
|
168
|
+
r.should be_a(GSolr::Ext::Response::Facets)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should create a doc with gsolr_ext methods' do
|
172
|
+
r = create_response
|
173
|
+
|
174
|
+
doc = r.docs.first
|
175
|
+
doc.has?(:cat, /^elec/).should == true
|
176
|
+
doc.has?(:cat, 'elec').should_not == true
|
177
|
+
doc.has?(:cat, 'electronics').should == true
|
178
|
+
|
179
|
+
doc.get(:cat).should == 'electronics, hard drive'
|
180
|
+
doc.get(:xyz).should == nil
|
181
|
+
doc.get(:xyz, :default=>'def').should == 'def'
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should provide facet helpers' do
|
185
|
+
r = create_response
|
186
|
+
r.facets.size.should == 2
|
187
|
+
|
188
|
+
field_names = r.facets.collect{|facet|facet.name}
|
189
|
+
field_names.include?('cat').should == true
|
190
|
+
field_names.include?('manu').should == true
|
191
|
+
|
192
|
+
first_facet = r.facets.first
|
193
|
+
first_facet.name.should == 'cat'
|
194
|
+
|
195
|
+
first_facet.items.size.should == 10
|
196
|
+
|
197
|
+
expected = "electronics - 14, memory - 3, card - 2, connector - 2, drive - 2, graphics - 2, hard - 2, monitor - 2, search - 2, software - 2"
|
198
|
+
received = first_facet.items.collect do |item|
|
199
|
+
item.value + ' - ' + item.hits.to_s
|
200
|
+
end.join(', ')
|
201
|
+
|
202
|
+
expected.should == received
|
203
|
+
|
204
|
+
r.facets.each do |facet|
|
205
|
+
facet.respond_to?(:name).should == true
|
206
|
+
facet.items.each do |item|
|
207
|
+
item.respond_to?(:value).should == true
|
208
|
+
item.respond_to?(:hits).should == true
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'should return the correct value when calling facet_by_field_name' do
|
215
|
+
r = create_response
|
216
|
+
facet = r.facet_by_field_name('cat')
|
217
|
+
facet.name.should == 'cat'
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'should provide the responseHeader params' do
|
221
|
+
raw_response = eval(mock_query_response)
|
222
|
+
raw_response['responseHeader']['params']['test'] = :test
|
223
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', raw_response['params'])
|
224
|
+
r.params['test'].should == :test
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should provide the solr-returned params and "rows" should be 11' do
|
228
|
+
raw_response = eval(mock_query_response)
|
229
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', {})
|
230
|
+
r.params[:rows].to_s.should == '11'
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'should provide the ruby request params if responseHeader["params"] does not exist' do
|
234
|
+
raw_response = eval(mock_query_response)
|
235
|
+
raw_response.delete 'responseHeader'
|
236
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', :rows => 999)
|
237
|
+
r.params[:rows].to_s.should == '999'
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'should provide spelling suggestions for regular spellcheck results' do
|
241
|
+
raw_response = eval(mock_response_with_spellcheck)
|
242
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', {})
|
243
|
+
r.spelling.words.should include("dell")
|
244
|
+
r.spelling.words.should include("ultrasharp")
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'should provide spelling suggestions for extended spellcheck results' do
|
248
|
+
raw_response = eval(mock_response_with_spellcheck_extended)
|
249
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', {})
|
250
|
+
r.spelling.words.should include("dell")
|
251
|
+
r.spelling.words.should include("ultrasharp")
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should provide no spelling suggestions when extended results and suggestion frequency is the same as original query frequency' do
|
255
|
+
raw_response = eval(mock_response_with_spellcheck_same_frequency)
|
256
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', {})
|
257
|
+
r.spelling.words.should == []
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'should provide spelling suggestions for a regular spellcheck results with a collation' do
|
261
|
+
raw_response = eval(mock_response_with_spellcheck_collation)
|
262
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', {})
|
263
|
+
r.spelling.words.should include("dell")
|
264
|
+
r.spelling.words.should include("ultrasharp")
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'should provide spelling suggestion collation' do
|
268
|
+
raw_response = eval(mock_response_with_spellcheck_collation)
|
269
|
+
r = GSolr::Ext::Response::Base.new(raw_response, '/catalog', {})
|
270
|
+
r.spelling.collation.should == 'dell ultrasharp'
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
|