Skip to content

Commit 44ba0fc

Browse files
author
Mat Brown
committed
Partial implementation of Dismax component
No support yet for boost queries or boost functions
1 parent f0b8f74 commit 44ba0fc

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

lib/soolr.rb

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ module Soolr
1010

1111
autoload :Field, 'soolr/field'
1212

13+
autoload :Dismax, 'soolr/dismax'
14+
1315
autoload :AllOf, 'soolr/all_of'
1416
autoload :AnyOf, 'soolr/any_of'
1517
autoload :Between, 'soolr/between'

lib/soolr/dismax.rb

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
module Soolr
2+
class Dismax
3+
FieldWithBoost = Struct.new(:field, :boost, :phrase_boost)
4+
5+
attr_writer :minimum_match, :phrase_slop, :query_phrase_slop, :tie_breaker
6+
7+
def initialize(keywords)
8+
@keywords, @fields = keywords, []
9+
end
10+
11+
def add_field(field, options = {})
12+
@fields << FieldWithBoost.new(field, options[:boost], options[:phrase_boost])
13+
end
14+
15+
def to_params
16+
fields = []
17+
phrase_fields = []
18+
@fields.each do |field_with_boost|
19+
fields <<
20+
if field_with_boost.boost
21+
"#{field_with_boost.field.name}^#{field_with_boost.boost}"
22+
else
23+
field_with_boost.field.name
24+
end
25+
if field_with_boost.phrase_boost
26+
phrase_fields << "#{field_with_boost.field.name}^#{field_with_boost.phrase_boost}"
27+
end
28+
end
29+
30+
params = {
31+
:q => @keywords,
32+
:qt => 'dismax',
33+
:qf => fields.join(' ')
34+
}
35+
params[:mm] = @minimum_match if @minimum_match
36+
params[:pf] = phrase_fields.join(' ') unless phrase_fields.empty?
37+
params[:ps] = @phrase_slop if @phrase_slop
38+
params[:qs] = @query_phrase_slop if @query_phrase_slop
39+
params[:tie] = @tie_breaker if @tie_breaker
40+
params
41+
end
42+
end
43+
end

spec/examples/dismax_spec.rb

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
require File.expand_path('../spec_helper', __FILE__)
2+
3+
describe Soolr::Dismax do
4+
let(:headline) { Soolr::Field.new(:headline, Soolr::StringType) }
5+
let(:body) { Soolr::Field.new(:body, Soolr::StringType) }
6+
7+
describe '#to_params' do
8+
it 'should have :q param' do
9+
params_from('pizza')[:q].should == 'pizza'
10+
end
11+
12+
it 'should set :qt param to "dismax"' do
13+
params_from('pizza')[:qt].should == 'dismax'
14+
end
15+
16+
it 'should set :qf param' do
17+
params_from('pizza') do |dismax|
18+
dismax.add_field(headline)
19+
end[:qf].should == 'headline'
20+
end
21+
22+
it 'should set multiple fields in :qf param' do
23+
params_from('pizza') do |dismax|
24+
dismax.add_field(headline)
25+
dismax.add_field(body)
26+
end[:qf].should == 'headline body'
27+
end
28+
29+
it 'should set boost in :qf param if given' do
30+
params_from('pizza') do |dismax|
31+
dismax.add_field(headline, :boost => 2.0)
32+
dismax.add_field(body)
33+
end[:qf].should == 'headline^2.0 body'
34+
end
35+
36+
it 'should set minimum match' do
37+
params_from('pizza pasta pepperoni') do |dismax|
38+
dismax.minimum_match = 2
39+
end[:mm].should == 2
40+
end
41+
42+
it 'should set phrase fields' do
43+
params_from('pizza') do |dismax|
44+
dismax.add_field(headline, :phrase_boost => 5.0)
45+
dismax.add_field(body, :phrase_boost => 2.0)
46+
end[:pf].should == 'headline^5.0 body^2.0'
47+
end
48+
49+
it 'should set phrase slop' do
50+
params_from('pizza') do |dismax|
51+
dismax.phrase_slop = 2
52+
end[:ps].should == 2
53+
end
54+
55+
it 'should set query phrase slop' do
56+
params_from('pizza') do |dismax|
57+
dismax.query_phrase_slop = 2
58+
end[:qs].should == 2
59+
end
60+
61+
it 'should set tie breaker' do
62+
params_from('pizza') do |dismax|
63+
dismax.tie_breaker = 0.1
64+
end[:tie].should == 0.1
65+
end
66+
end
67+
68+
private
69+
70+
def dismax(keywords)
71+
dismax = Soolr::Dismax.new(keywords)
72+
yield dismax if block_given?
73+
dismax
74+
end
75+
76+
def params_from(keywords, &block)
77+
dismax(keywords, &block).to_params
78+
end
79+
end

0 commit comments

Comments
 (0)