Permalink
Browse files

Add specs to test spellcheck feature; Modify solrconfig.xml to add sp…

…ellcheck components to standard and dismax handlers

Conflicts:

	sunspot/lib/sunspot/query.rb
  • Loading branch information...
1 parent 489806a commit 07cf4610d960d2db3077d8200710e90d477ff17a Cuong Hoang committed with Jan 19, 2012
@@ -118,6 +118,16 @@ def with(*args)
# else
super
end
+
+ # Ask Solr to suggest alternative spellings for the query
+ #
+ # ==== Options
+ #
+ # The list of options can be found here: http://wiki.apache.org/solr/SpellCheckComponent
+ def spellcheck(options = {})
+ @query.add_spellcheck(options)
+ end
+
end
end
end
@@ -1,8 +1,8 @@
%w(filter abstract_field_facet connective boost_query date_field_facet dismax
field_facet highlighting pagination restriction common_query
- standard_query more_like_this more_like_this_query geo geofilt bbox query_facet
- scope sort sort_composite text_field_boost function_query
- composite_fulltext field_group).each do |file|
+ standard_query more_like_this more_like_this_query geo geofilt query_facet scope
+ sort sort_composite text_field_boost function_query
+ composite_fulltext field_group spellcheck).each do |file|
require(File.join(File.dirname(__FILE__), 'query', file))
end
module Sunspot
@@ -45,6 +45,11 @@ def add_geo(geo)
geo
end
+
+ def add_spellcheck(options = {})
+ @components << Spellcheck.new(options)
+ end
+
def paginate(page, per_page, offset = nil)
if @pagination
@pagination.offset = offset
@@ -0,0 +1,19 @@
+module Sunspot
+ module Query
+ class Spellcheck < Connective::Conjunction
+ attr_accessor :options
+
+ def initialize(options = {})
+ @options = options
+ end
+
+ def to_params
+ options = {}
+ @options.each do |key, val|
+ options["spellcheck." + Sunspot::Util.method_case(key.to_s)] = val
+ end
+ { :spellcheck => true }.merge(options)
+ end
+ end
+ end
+end
@@ -57,7 +57,7 @@ def spellcheck_collation(*terms)
# If we are given a query string, tokenize it and strictly replace
# the terms that aren't present in the index
- if terms.present?
+ if terms.length > 0
terms.each do |term|
if (spellcheck_suggestions[term]||{})['origFreq'] == 0
collation[term] = spellcheck_suggestion_for(term)
@@ -53,6 +53,23 @@ def camel_case(string)
string.split('_').map! { |word| word.capitalize }.join
end
+
+ #
+ # Convert snake case string to method case (Java style)
+ #
+ # ==== Parameters
+ #
+ # string<String>:: String to convert to method case
+ #
+ # ==== Returns
+ #
+ # String:: String in method case
+ #
+ def method_case(string)
+ first = true
+ string.split('_').map! { |word| word = first ? word : word.capitalize; first = false; word }.join
+ end
+
#
# Get a constant from a fully qualified name
#
@@ -0,0 +1,21 @@
+require File.expand_path('spec_helper', File.dirname(__FILE__))
+
+shared_examples_for 'spellcheck query' do
+
+ it 'sends spellcheck parameters to solr' do
+ search do
+ spellcheck
+ end
+ connection.should have_last_search_including(:spellcheck, true)
+ end
+
+
+ it "sends additional spellcheck parameters with camel casing" do
+ search do
+ spellcheck :only_more_popular => true, :count => 5
+ end
+ connection.should have_last_search_including('spellcheck.onlyMorePopular', true)
+ connection.should have_last_search_including('spellcheck.count', 5)
+ end
+
+end
@@ -12,6 +12,7 @@
it_should_behave_like "query with text field scoping"
it_should_behave_like "geohash query"
it_should_behave_like "spatial query"
+ it_should_behave_like "spellcheck query"
it 'adds a no-op query to :q parameter when no :q provided' do
session.search Post do
@@ -0,0 +1,59 @@
+require File.expand_path('../spec_helper', File.dirname(__FILE__))
+include SearchHelper
+
+describe 'spellcheck' do
+ before :each do
+ Sunspot.remove_all
+
+ @posts = [
+ Post.new(:title => 'Java Developer'),
+ Post.new(:title => 'Lava Flow'),
+ Post.new(:title => 'Java Analyst'),
+ Post.new(:title => 'C++ Developer'),
+ Post.new(:title => 'C++ Developing')
+ ]
+
+ Sunspot.index!(*@posts)
+ Sunspot.commit
+ end
+
+ it 'returns the list of suggestions' do
+ search = Sunspot.search(Post) do
+ keywords 'Wava'
+ spellcheck :count => 3
+ end
+
+ search.spellcheck_suggestions['Wava']['suggestion'].should == [{'word'=>'java', 'freq'=>2}, {'word'=>'lava', 'freq'=>1}]
+ end
+
+ it 'returns suggestion with highest frequency' do
+ search = Sunspot.search(Post) do
+ keywords 'Wava'
+ spellcheck :count => 3
+ end
+
+ search.spellcheck_suggestion_for('Wava').should == 'java'
+ end
+
+ context 'spellcheck collation' do
+
+ it 'replaces terms that are not in the index if terms are provided' do
+
+ search = Sunspot.search(Post) do
+ keywords 'wava developing'
+ spellcheck :count => 3, :only_more_popular => true
+ end
+ search.spellcheck_collation('wava', 'developing').should == 'java developing'
+ end
+
+ it 'returns Solr collation if terms are not provided' do
+
+ search = Sunspot.search(Post) do
+ keywords 'wava developing'
+ spellcheck :count => 3, :only_more_popular => true
+ end
+ search.spellcheck_collation.should == 'java developer'
+ end
+ end
+
+end
@@ -441,7 +441,13 @@
<str name="fl">*</str>
<str name="version">2.1</str>
-->
+ <str name="spellcheck.dictionary">default</str>
+ <str name="spellcheck.extendedResults">true</str>
+ <str name="spellcheck.collate">true</str>
</lst>
+ <arr name="last-components">
+ <str>spellcheck</str>
+ </arr>
</requestHandler>
<!-- Please refer to http://wiki.apache.org/solr/SolrReplication for details on configuring replication -->
<!-- remove the <lst name="master"> section if this is just a slave -->
@@ -495,7 +501,13 @@
<str name="f.name.hl.alternateField">name</str>
<str name="f.text.hl.fragmenter">regex</str>
<!-- defined below -->
+ <str name="spellcheck.dictionary">default</str>
+ <str name="spellcheck.extendedResults">true</str>
+ <str name="spellcheck.collate">true</str>
</lst>
+ <arr name="last-components">
+ <str>spellcheck</str>
+ </arr>
</requestHandler>
<!-- Note how you can register the same handler multiple times with
different names (and different init parameters)
@@ -589,8 +601,9 @@
<str name="queryAnalyzerFieldType">textSpell</str>
<lst name="spellchecker">
<str name="name">default</str>
- <str name="field">name</str>
+ <str name="field">title_text</str>
<str name="spellcheckIndexDir">./spellchecker</str>
+ <str name="buildOnCommit">true</str>
</lst>
<!-- a spellchecker that uses a different distance measure
<lst name="spellchecker">

0 comments on commit 07cf461

Please sign in to comment.