ansr 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +35 -0
- data/ansr.gemspec +2 -1
- data/ansr_blacklight/Gemfile +3 -0
- data/ansr_blacklight/README.md +37 -0
- data/ansr_blacklight/ansr_blacklight.gemspec +28 -0
- data/ansr_blacklight/lib/ansr_blacklight.rb +57 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel.rb +6 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/big_table.rb +57 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/visitors.rb +6 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/query_builder.rb +217 -0
- data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/to_no_sql.rb +14 -0
- data/ansr_blacklight/lib/ansr_blacklight/base.rb +21 -0
- data/ansr_blacklight/lib/ansr_blacklight/connection_adapters/no_sql_adapter.rb +38 -0
- data/ansr_blacklight/lib/ansr_blacklight/model/querying.rb +29 -0
- data/ansr_blacklight/lib/ansr_blacklight/relation.rb +50 -0
- data/ansr_blacklight/lib/ansr_blacklight/relation/solr_projection_methods.rb +55 -0
- data/ansr_blacklight/lib/ansr_blacklight/request_builders.rb +141 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr.rb +4 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/request.rb +46 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response.rb +94 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/group.rb +32 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/group_response.rb +50 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/more_like_this.rb +14 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/pagination_methods.rb +35 -0
- data/ansr_blacklight/lib/ansr_blacklight/solr/response/spelling.rb +92 -0
- data/ansr_blacklight/spec/fixtures/config.yml +0 -0
- data/ansr_blacklight/spec/lib/loaded_relation_spec.rb +223 -0
- data/ansr_blacklight/spec/lib/queryable_relation_spec.rb +133 -0
- data/ansr_blacklight/spec/lib/relation/faceting_spec.rb +475 -0
- data/ansr_blacklight/spec/lib/relation/grouping_spec.rb +159 -0
- data/ansr_blacklight/spec/spec_helper.rb +72 -0
- data/ansr_dpla/Gemfile +3 -0
- data/ansr_dpla/Gemfile.lock +138 -0
- data/ansr_dpla/README.md +2 -2
- data/ansr_dpla/ansr_dpla.gemspec +2 -2
- data/ansr_dpla/lib/ansr_dpla.rb +3 -0
- data/ansr_dpla/lib/ansr_dpla/api.rb +3 -3
- data/ansr_dpla/lib/ansr_dpla/arel.rb +1 -2
- data/ansr_dpla/lib/ansr_dpla/arel/big_table.rb +4 -0
- data/ansr_dpla/lib/ansr_dpla/arel/visitors.rb +6 -0
- data/ansr_dpla/lib/ansr_dpla/arel/visitors/query_builder.rb +188 -0
- data/ansr_dpla/lib/ansr_dpla/arel/visitors/to_no_sql.rb +9 -0
- data/ansr_dpla/lib/ansr_dpla/connection_adapters/no_sql_adapter.rb +58 -0
- data/ansr_dpla/lib/ansr_dpla/model/base.rb +7 -0
- data/ansr_dpla/lib/ansr_dpla/model/querying.rb +6 -10
- data/ansr_dpla/lib/ansr_dpla/relation.rb +61 -0
- data/ansr_dpla/lib/ansr_dpla/request.rb +5 -0
- data/ansr_dpla/spec/lib/api_spec.rb +8 -5
- data/ansr_dpla/spec/lib/item_spec.rb +2 -2
- data/ansr_dpla/spec/lib/relation/facet_spec.rb +27 -19
- data/ansr_dpla/spec/lib/relation/select_spec.rb +10 -8
- data/ansr_dpla/spec/lib/relation/where_spec.rb +1 -1
- data/ansr_dpla/spec/lib/relation_spec.rb +31 -29
- data/ansr_dpla/test/system.rb +4 -2
- data/lib/ansr.rb +7 -0
- data/lib/ansr/arel.rb +3 -0
- data/lib/ansr/arel/big_table.rb +43 -3
- data/lib/ansr/arel/configured_field.rb +19 -0
- data/lib/ansr/arel/nodes.rb +41 -0
- data/lib/ansr/arel/visitors.rb +7 -0
- data/lib/ansr/arel/visitors/context.rb +13 -0
- data/lib/ansr/arel/visitors/query_builder.rb +47 -0
- data/lib/ansr/arel/visitors/to_no_sql.rb +41 -0
- data/lib/ansr/base.rb +29 -1
- data/lib/ansr/configurable.rb +6 -12
- data/lib/ansr/connection_adapters.rb +5 -0
- data/lib/ansr/connection_adapters/no_sql_adapter.rb +80 -0
- data/lib/ansr/dummy_associations.rb +105 -0
- data/lib/ansr/facets.rb +103 -0
- data/lib/ansr/model.rb +17 -107
- data/lib/ansr/model/connection_handler.rb +6 -0
- data/lib/ansr/relation.rb +40 -23
- data/lib/ansr/relation/group.rb +31 -0
- data/lib/ansr/relation/predicate_builder.rb +106 -0
- data/lib/ansr/relation/query_methods.rb +192 -45
- data/lib/ansr/sanitization.rb +5 -18
- data/lib/ansr/utils.rb +89 -0
- data/lib/ansr/version.rb +1 -1
- metadata +73 -25
- data/ansr_dpla/lib/ansr_dpla/arel/connection.rb +0 -81
- data/ansr_dpla/lib/ansr_dpla/arel/query_builder.rb +0 -131
- data/lib/ansr/model/connection.rb +0 -103
@@ -0,0 +1,32 @@
|
|
1
|
+
class Ansr::Blacklight::Solr::Response::Group < Ansr::Group
|
2
|
+
|
3
|
+
include Ansr::Blacklight::Solr::Response::PaginationMethods
|
4
|
+
|
5
|
+
attr_reader :response
|
6
|
+
|
7
|
+
def initialize group_key, model, group, response
|
8
|
+
super(group_key, model, group)
|
9
|
+
@response = response
|
10
|
+
end
|
11
|
+
|
12
|
+
def doclist
|
13
|
+
group[:doclist]
|
14
|
+
end
|
15
|
+
|
16
|
+
# short cut to response['numFound']
|
17
|
+
def total
|
18
|
+
doclist[:numFound].to_s.to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def start
|
22
|
+
doclist[:start].to_s.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def docs
|
26
|
+
doclist[:docs].map {|doc| model.new(doc)} #TODO do we need to have the solrResponse in the item?
|
27
|
+
end
|
28
|
+
|
29
|
+
def field
|
30
|
+
response.group_field
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Ansr::Blacklight::Solr::Response::GroupResponse
|
2
|
+
|
3
|
+
include Ansr::Blacklight::Solr::Response::PaginationMethods
|
4
|
+
|
5
|
+
attr_reader :key, :model, :group, :response
|
6
|
+
|
7
|
+
def initialize key, model, group, response
|
8
|
+
@key = key
|
9
|
+
@model = model
|
10
|
+
@group = group
|
11
|
+
@response = response
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :group_field, :key
|
15
|
+
|
16
|
+
def groups
|
17
|
+
@groups ||= group["groups"].map do |g|
|
18
|
+
Ansr::Blacklight::Solr::Response::Group.new({key => g[:groupValue]}, model, g, self)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def group_limit
|
23
|
+
params.fetch(:'group.limit', 1).to_s.to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
def total
|
27
|
+
# ngroups is only available in Solr 4.1+
|
28
|
+
# fall back on the number of facet items for that field?
|
29
|
+
(group["ngroups"] || (response.facet_by_field_name(key) || []).length).to_s.to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
def start
|
33
|
+
params[:start].to_s.to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing meth, *args, &block
|
37
|
+
|
38
|
+
if response.respond_to? meth
|
39
|
+
response.send(meth, *args, &block)
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def respond_to? meth
|
47
|
+
response.respond_to?(meth) || super
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Ansr::Blacklight::Solr::Response::MoreLikeThis
|
2
|
+
def more_like document
|
3
|
+
mlt = more_like_this[document.id]
|
4
|
+
return [] unless mlt and mlt['docs']
|
5
|
+
|
6
|
+
mlt['docs']
|
7
|
+
end
|
8
|
+
|
9
|
+
def more_like_this
|
10
|
+
return {} unless self[:moreLikeThis]
|
11
|
+
|
12
|
+
self[:moreLikeThis]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'kaminari'
|
2
|
+
module Ansr::Blacklight::Solr::Response::PaginationMethods
|
3
|
+
|
4
|
+
include Kaminari::PageScopeMethods
|
5
|
+
include Kaminari::ConfigurationMethods::ClassMethods
|
6
|
+
|
7
|
+
def limit_value #:nodoc:
|
8
|
+
rows
|
9
|
+
end
|
10
|
+
|
11
|
+
def offset_value #:nodoc:
|
12
|
+
start
|
13
|
+
end
|
14
|
+
|
15
|
+
def total_count #:nodoc:
|
16
|
+
total
|
17
|
+
end
|
18
|
+
|
19
|
+
def model_name
|
20
|
+
if !docs.empty? and docs.first.respond_to? :model_name
|
21
|
+
docs.first.model_name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
## Methods in kaminari master that we'd like to use today.
|
26
|
+
# Next page number in the collection
|
27
|
+
def next_page
|
28
|
+
current_page + 1 unless last_page?
|
29
|
+
end
|
30
|
+
|
31
|
+
# Previous page number in the collection
|
32
|
+
def prev_page
|
33
|
+
current_page - 1 unless first_page?
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# A mixin for making access to the spellcheck component data easy.
|
2
|
+
#
|
3
|
+
# response.spelling.words
|
4
|
+
#
|
5
|
+
module Ansr::Blacklight::Solr::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
|
+
|
File without changes
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ansr::Blacklight::Relation do
|
4
|
+
|
5
|
+
def create_response
|
6
|
+
raw_response = eval(mock_query_response)
|
7
|
+
Blacklight::SolrResponse.new(raw_response, raw_response['params'])
|
8
|
+
end
|
9
|
+
|
10
|
+
def stub_solr
|
11
|
+
@solr ||= double('Solr')
|
12
|
+
@solr.stub(:send_and_receive).and_return(mock_query_response)
|
13
|
+
@solr
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
Object.const_set('LoadTestModel', Class.new(TestModel))
|
18
|
+
LoadTestModel.solr = stub_solr
|
19
|
+
LoadTestModel.solr = stub_solr
|
20
|
+
@relation = Ansr::Blacklight::Relation.new(LoadTestModel, Ansr::Arel::BigTable.new(LoadTestModel))
|
21
|
+
@relation.load
|
22
|
+
end
|
23
|
+
after do
|
24
|
+
Object.send(:remove_const, :LoadTestModel)
|
25
|
+
end
|
26
|
+
subject { @relation }
|
27
|
+
|
28
|
+
let(:r) { subject }
|
29
|
+
|
30
|
+
describe 'pagination' do
|
31
|
+
it 'should have accurate pagination numbers' do
|
32
|
+
expect(r.limit_value).to eq 11
|
33
|
+
expect(r.count).to eq 26
|
34
|
+
expect(r.offset_value).to eq 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should provide kaminari pagination helpers" do
|
38
|
+
expect(r.total_count).to eq(r.count)
|
39
|
+
expect(r.next_page).to eq(r.current_page + 1)
|
40
|
+
expect(r.prev_page).to eq(nil)
|
41
|
+
if Kaminari.config.respond_to? :max_pages
|
42
|
+
expect(r.max_pages).to be_nil
|
43
|
+
end
|
44
|
+
expect(r).to be_a_kind_of Kaminari::PageScopeMethods
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should create a valid response class' do
|
49
|
+
expect(r).to respond_to(:response)
|
50
|
+
expect(r.docs).to have(11).docs
|
51
|
+
expect(r.params[:echoParams]).to eq 'EXPLICIT'
|
52
|
+
|
53
|
+
expect(r).to respond_to(:facets)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should provide facet helpers' do
|
57
|
+
r.facets.size.should == 2
|
58
|
+
|
59
|
+
field_names = r.facets.collect{|facet|facet.name}
|
60
|
+
field_names.include?('cat').should == true
|
61
|
+
field_names.include?('manu').should == true
|
62
|
+
|
63
|
+
first_facet = r.facets.select { |x| x.name == 'cat'}.first
|
64
|
+
first_facet.name.should == 'cat'
|
65
|
+
|
66
|
+
first_facet.items.size.should == 10
|
67
|
+
|
68
|
+
expected = "electronics - 14, memory - 3, card - 2, connector - 2, drive - 2, graphics - 2, hard - 2, monitor - 2, search - 2, software - 2"
|
69
|
+
received = first_facet.items.collect do |item|
|
70
|
+
item.value + ' - ' + item.hits.to_s
|
71
|
+
end.join(', ')
|
72
|
+
|
73
|
+
expect(received).to eq expected
|
74
|
+
|
75
|
+
r.facets.each do |facet|
|
76
|
+
expect(facet).to respond_to :name
|
77
|
+
expect(facet).to respond_to :sort
|
78
|
+
expect(facet).to respond_to :offset
|
79
|
+
expect(facet).to respond_to :limit
|
80
|
+
facet.items.each do |item|
|
81
|
+
expect(item).to respond_to :value
|
82
|
+
expect(item).to respond_to :hits
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should provide a model name helper" do
|
88
|
+
expect(r.model_name).to eq LoadTestModel.name
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "FacetItem" do
|
92
|
+
it "should work with a field,value tuple" do
|
93
|
+
item = Ansr::Facets::FacetItem.new('value', 15)
|
94
|
+
puts item.class.name
|
95
|
+
item.value.should == 'value'
|
96
|
+
item.hits.should == 15
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should work with a field,value + hash triple" do
|
100
|
+
item = Ansr::Facets::FacetItem.new('value', 15, :a => 1, :value => 'ignored')
|
101
|
+
item.value.should == 'value'
|
102
|
+
item.hits.should == 15
|
103
|
+
item.a.should == 1
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should work like an openstruct" do
|
107
|
+
item = Ansr::Facets::FacetItem.new(:value => 'value', :hits => 15)
|
108
|
+
|
109
|
+
item.hits.should == 15
|
110
|
+
item.value.should == 'value'
|
111
|
+
item.should be_a_kind_of(OpenStruct)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should provide a label accessor" do
|
115
|
+
item = Ansr::Facets::FacetItem.new('value', :hits => 15)
|
116
|
+
item.label.should == 'value'
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should use a provided label" do
|
120
|
+
item = Ansr::Facets::FacetItem.new('value', 15, :label => 'custom label')
|
121
|
+
item.label.should == 'custom label'
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should return the correct value when calling facet_by_field_name' do
|
128
|
+
r = create_response
|
129
|
+
facet = r.facet_by_field_name('cat')
|
130
|
+
facet.name.should == 'cat'
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should provide the responseHeader params' do
|
134
|
+
raw_response = eval(mock_query_response)
|
135
|
+
raw_response['responseHeader']['params']['test'] = :test
|
136
|
+
r = Blacklight::SolrResponse.new(raw_response, raw_response['params'])
|
137
|
+
r.params['test'].should == :test
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should provide the solr-returned params and "rows" should be 11' do
|
141
|
+
raw_response = eval(mock_query_response)
|
142
|
+
r = Blacklight::SolrResponse.new(raw_response, {})
|
143
|
+
r.params[:rows].to_s.should == '11'
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should provide the ruby request params if responseHeader["params"] does not exist' do
|
147
|
+
raw_response = eval(mock_query_response)
|
148
|
+
raw_response.delete 'responseHeader'
|
149
|
+
r = Blacklight::SolrResponse.new(raw_response, :rows => 999)
|
150
|
+
r.params[:rows].to_s.should == '999'
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should provide spelling suggestions for regular spellcheck results' do
|
154
|
+
raw_response = eval(mock_response_with_spellcheck)
|
155
|
+
r = Blacklight::SolrResponse.new(raw_response, {})
|
156
|
+
r.spelling.words.should include("dell")
|
157
|
+
r.spelling.words.should include("ultrasharp")
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'should provide spelling suggestions for extended spellcheck results' do
|
161
|
+
raw_response = eval(mock_response_with_spellcheck_extended)
|
162
|
+
r = Blacklight::SolrResponse.new(raw_response, {})
|
163
|
+
r.spelling.words.should include("dell")
|
164
|
+
r.spelling.words.should include("ultrasharp")
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should provide no spelling suggestions when extended results and suggestion frequency is the same as original query frequency' do
|
168
|
+
raw_response = eval(mock_response_with_spellcheck_same_frequency)
|
169
|
+
r = Blacklight::SolrResponse.new(raw_response, {})
|
170
|
+
r.spelling.words.should == []
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should provide spelling suggestions for a regular spellcheck results with a collation' do
|
174
|
+
raw_response = eval(mock_response_with_spellcheck_collation)
|
175
|
+
r = Blacklight::SolrResponse.new(raw_response, {})
|
176
|
+
r.spelling.words.should include("dell")
|
177
|
+
r.spelling.words.should include("ultrasharp")
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should provide spelling suggestion collation' do
|
181
|
+
raw_response = eval(mock_response_with_spellcheck_collation)
|
182
|
+
r = Blacklight::SolrResponse.new(raw_response, {})
|
183
|
+
r.spelling.collation.should == 'dell ultrasharp'
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should provide MoreLikeThis suggestions" do
|
187
|
+
raw_response = eval(mock_response_with_more_like_this)
|
188
|
+
r = Blacklight::SolrResponse.new(raw_response, {})
|
189
|
+
r.more_like(double(:id => '79930185')).should have(2).items
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should be empty when the response has no results" do
|
193
|
+
r = Blacklight::SolrResponse.new({}, {})
|
194
|
+
r.stub(:total => 0)
|
195
|
+
expect(r).to be_empty
|
196
|
+
end
|
197
|
+
|
198
|
+
def mock_query_response
|
199
|
+
%({'responseHeader'=>{'status'=>0,'QTime'=>5,'params'=>{'facet.limit'=>'10','wt'=>'ruby','rows'=>'11','facet'=>'true','facet.field'=>['cat','manu'],'echoParams'=>'EXPLICIT','q'=>'*:*','facet.sort'=>'true'}},'response'=>{'numFound'=>26,'start'=>0,'docs'=>[{'id'=>'SP2514N','inStock'=>true,'manu'=>'Samsung Electronics Co. Ltd.','name'=>'Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133','popularity'=>6,'price'=>92.0,'sku'=>'SP2514N','timestamp'=>'2009-03-20T14:42:49.795Z','cat'=>['electronics','hard drive'],'spell'=>['Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133'],'features'=>['7200RPM, 8MB cache, IDE Ultra ATA-133','NoiseGuard, SilentSeek technology, Fluid Dynamic Bearing (FDB) motor']},{'id'=>'6H500F0','inStock'=>true,'manu'=>'Maxtor Corp.','name'=>'Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300','popularity'=>6,'price'=>350.0,'sku'=>'6H500F0','timestamp'=>'2009-03-20T14:42:49.877Z','cat'=>['electronics','hard drive'],'spell'=>['Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300'],'features'=>['SATA 3.0Gb/s, NCQ','8.5ms seek','16MB cache']},{'id'=>'F8V7067-APL-KIT','inStock'=>false,'manu'=>'Belkin','name'=>'Belkin Mobile Power Cord for iPod w/ Dock','popularity'=>1,'price'=>19.95,'sku'=>'F8V7067-APL-KIT','timestamp'=>'2009-03-20T14:42:49.937Z','weight'=>4.0,'cat'=>['electronics','connector'],'spell'=>['Belkin Mobile Power Cord for iPod w/ Dock'],'features'=>['car power adapter, white']},{'id'=>'IW-02','inStock'=>false,'manu'=>'Belkin','name'=>'iPod & iPod Mini USB 2.0 Cable','popularity'=>1,'price'=>11.5,'sku'=>'IW-02','timestamp'=>'2009-03-20T14:42:49.944Z','weight'=>2.0,'cat'=>['electronics','connector'],'spell'=>['iPod & iPod Mini USB 2.0 Cable'],'features'=>['car power adapter for iPod, white']},{'id'=>'MA147LL/A','inStock'=>true,'includes'=>'earbud headphones, USB cable','manu'=>'Apple Computer Inc.','name'=>'Apple 60 GB iPod with Video Playback Black','popularity'=>10,'price'=>399.0,'sku'=>'MA147LL/A','timestamp'=>'2009-03-20T14:42:49.962Z','weight'=>5.5,'cat'=>['electronics','music'],'spell'=>['Apple 60 GB iPod with Video Playback Black'],'features'=>['iTunes, Podcasts, Audiobooks','Stores up to 15,000 songs, 25,000 photos, or 150 hours of video','2.5-inch, 320x240 color TFT LCD display with LED backlight','Up to 20 hours of battery life','Plays AAC, MP3, WAV, AIFF, Audible, Apple Lossless, H.264 video','Notes, Calendar, Phone book, Hold button, Date display, Photo wallet, Built-in games, JPEG photo playback, Upgradeable firmware, USB 2.0 compatibility, Playback speed control, Rechargeable capability, Battery level indication']},{'id'=>'TWINX2048-3200PRO','inStock'=>true,'manu'=>'Corsair Microsystems Inc.','name'=>'CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail','popularity'=>5,'price'=>185.0,'sku'=>'TWINX2048-3200PRO','timestamp'=>'2009-03-20T14:42:49.99Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail'],'features'=>['CAS latency 2, 2-3-3-6 timing, 2.75v, unbuffered, heat-spreader']},{'id'=>'VS1GB400C3','inStock'=>true,'manu'=>'Corsair Microsystems Inc.','name'=>'CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail','popularity'=>7,'price'=>74.99,'sku'=>'VS1GB400C3','timestamp'=>'2009-03-20T14:42:50Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail']},{'id'=>'VDBDB1A16','inStock'=>true,'manu'=>'A-DATA Technology Inc.','name'=>'A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM','popularity'=>5,'sku'=>'VDBDB1A16','timestamp'=>'2009-03-20T14:42:50.004Z','cat'=>['electronics','memory'],'spell'=>['A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM'],'features'=>['CAS latency 3, 2.7v']},{'id'=>'3007WFP','inStock'=>true,'includes'=>'USB cable','manu'=>'Dell, Inc.','name'=>'Dell Widescreen UltraSharp 3007WFP','popularity'=>6,'price'=>2199.0,'sku'=>'3007WFP','timestamp'=>'2009-03-20T14:42:50.017Z','weight'=>401.6,'cat'=>['electronics','monitor'],'spell'=>['Dell Widescreen UltraSharp 3007WFP'],'features'=>['30" TFT active matrix LCD, 2560 x 1600, .25mm dot pitch, 700:1 contrast']},{'id'=>'VA902B','inStock'=>true,'manu'=>'ViewSonic Corp.','name'=>'ViewSonic VA902B - flat panel display - TFT - 19"','popularity'=>6,'price'=>279.95,'sku'=>'VA902B','timestamp'=>'2009-03-20T14:42:50.034Z','weight'=>190.4,'cat'=>['electronics','monitor'],'spell'=>['ViewSonic VA902B - flat panel display - TFT - 19"'],'features'=>['19" TFT active matrix LCD, 8ms response time, 1280 x 1024 native resolution']},{'id'=>'0579B002','inStock'=>true,'manu'=>'Canon Inc.','name'=>'Canon PIXMA MP500 All-In-One Photo Printer','popularity'=>6,'price'=>179.99,'sku'=>'0579B002','timestamp'=>'2009-03-20T14:42:50.062Z','weight'=>352.0,'cat'=>['electronics','multifunction printer','printer','scanner','copier'],'spell'=>['Canon PIXMA MP500 All-In-One Photo Printer'],'features'=>['Multifunction ink-jet color photo printer','Flatbed scanner, optical scan resolution of 1,200 x 2,400 dpi','2.5" color LCD preview screen','Duplex Copying','Printing speed up to 29ppm black, 19ppm color','Hi-Speed USB','memory card: CompactFlash, Micro Drive, SmartMedia, Memory Stick, Memory Stick Pro, SD Card, and MultiMediaCard']}]},'facet_counts'=>{'facet_queries'=>{},'facet_fields'=>{'cat'=>['electronics',14,'memory',3,'card',2,'connector',2,'drive',2,'graphics',2,'hard',2,'monitor',2,'search',2,'software',2],'manu'=>['inc',8,'apach',2,'belkin',2,'canon',2,'comput',2,'corp',2,'corsair',2,'foundat',2,'microsystem',2,'softwar',2]},'facet_dates'=>{}}})
|
200
|
+
end
|
201
|
+
|
202
|
+
# These spellcheck responses are all Solr 1.4 responses
|
203
|
+
def mock_response_with_spellcheck
|
204
|
+
%|{'responseHeader'=>{'status'=>0,'QTime'=>9,'params'=>{'spellcheck'=>'true','spellcheck.collate'=>'true','wt'=>'ruby','q'=>'hell ultrashar'}},'response'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'spellcheck'=>{'suggestions'=>['hell',{'numFound'=>1,'startOffset'=>0,'endOffset'=>4,'suggestion'=>['dell']},'ultrashar',{'numFound'=>1,'startOffset'=>5,'endOffset'=>14,'suggestion'=>['ultrasharp']},'collation','dell ultrasharp']}}|
|
205
|
+
end
|
206
|
+
|
207
|
+
def mock_response_with_spellcheck_extended
|
208
|
+
%|{'responseHeader'=>{'status'=>0,'QTime'=>8,'params'=>{'spellcheck'=>'true','spellcheck.collate'=>'true','wt'=>'ruby','spellcheck.extendedResults'=>'true','q'=>'hell ultrashar'}},'response'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'spellcheck'=>{'suggestions'=>['hell',{'numFound'=>1,'startOffset'=>0,'endOffset'=>4,'origFreq'=>0,'suggestion'=>[{'word'=>'dell','freq'=>1}]},'ultrashar',{'numFound'=>1,'startOffset'=>5,'endOffset'=>14,'origFreq'=>0,'suggestion'=>[{'word'=>'ultrasharp','freq'=>1}]},'correctlySpelled',false,'collation','dell ultrasharp']}}|
|
209
|
+
end
|
210
|
+
|
211
|
+
def mock_response_with_spellcheck_same_frequency
|
212
|
+
%|{'responseHeader'=>{'status'=>0,'QTime'=>8,'params'=>{'spellcheck'=>'true','spellcheck.collate'=>'true','wt'=>'ruby','spellcheck.extendedResults'=>'true','q'=>'hell ultrashar'}},'response'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'spellcheck'=>{'suggestions'=>['hell',{'numFound'=>1,'startOffset'=>0,'endOffset'=>4,'origFreq'=>1,'suggestion'=>[{'word'=>'dell','freq'=>1}]},'ultrashard',{'numFound'=>1,'startOffset'=>5,'endOffset'=>14,'origFreq'=>1,'suggestion'=>[{'word'=>'ultrasharp','freq'=>1}]},'correctlySpelled',false,'collation','dell ultrasharp']}}|
|
213
|
+
end
|
214
|
+
|
215
|
+
# it can be the case that extended results are off and collation is on
|
216
|
+
def mock_response_with_spellcheck_collation
|
217
|
+
%|{'responseHeader'=>{'status'=>0,'QTime'=>3,'params'=>{'spellspellcheck.build'=>'true','spellcheck'=>'true','q'=>'hell','spellcheck.q'=>'hell ultrashar','wt'=>'ruby','spellcheck.collate'=>'true'}},'response'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'spellcheck'=>{'suggestions'=>['hell',{'numFound'=>1,'startOffset'=>0,'endOffset'=>4,'suggestion'=>['dell']},'ultrashar',{'numFound'=>1,'startOffset'=>5,'endOffset'=>14,'suggestion'=>['ultrasharp']},'collation','dell ultrasharp']}}|
|
218
|
+
end
|
219
|
+
|
220
|
+
def mock_response_with_more_like_this
|
221
|
+
%({'responseHeader'=>{'status'=>0,'QTime'=>8,'params'=>{'facet'=>'false','mlt.mindf'=>'1','mlt.fl'=>'subject_t','fl'=>'id','mlt.count'=>'3','mlt.mintf'=>'0','mlt'=>'true','q.alt'=>'*:*','qt'=>'search','wt'=>'ruby'}},'response'=>{'numFound'=>30,'start'=>0,'docs'=>[{'id'=>'00282214'},{'id'=>'00282371'},{'id'=>'00313831'},{'id'=>'00314247'},{'id'=>'43037890'},{'id'=>'53029833'},{'id'=>'77826928'},{'id'=>'78908283'},{'id'=>'79930185'},{'id'=>'85910001'}]},'moreLikeThis'=>{'00282214'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'00282371'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'00313831'=>{'numFound'=>1,'start'=>0,'docs'=>[{'id'=>'96933325'}]},'00314247'=>{'numFound'=>3,'start'=>0,'docs'=>[{'id'=>'2008543486'},{'id'=>'96933325'},{'id'=>'2009373513'}]},'43037890'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'53029833'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'77826928'=>{'numFound'=>1,'start'=>0,'docs'=>[{'id'=>'94120425'}]},'78908283'=>{'numFound'=>0,'start'=>0,'docs'=>[]},'79930185'=>{'numFound'=>2,'start'=>0,'docs'=>[{'id'=>'94120425'},{'id'=>'2007020969'}]},'85910001'=>{'numFound'=>0,'start'=>0,'docs'=>[]}}})
|
222
|
+
end
|
223
|
+
end
|