Rails engine that enables javascript-based autocomplete in the search query box and adds core support for spelling & completion suggesters.
This gem is based on code that worked with Solr 4.x, but the gem itself has only been tested with Solr 5.
- defines a SuggestionController
- defines a '/suggest' API endpoint on your application
Add this line to your blacklight application's Gemfile:
gem 'blacklight_suggest'
And then execute:
$ bundle
This gem is meant to be used as an add-on to Blacklight. It adds a 'suggestions' endpoint at /suggestions. To change this route, add a line like this to your config/routes.rb:
get '/suggest', to: 'suggestions#index', defaults: { format: 'json' }
In your schema.xml add fields for spelling and suggestions dictionaries. These fields must be indexed. They should not be stored. This example uses copyFields to include all *_s and *_sm dynamic fields in the dictionary. See the solr documentation, the default solr schema and the default solrconfig for more info about configuring spellcheck dictionaries.
<dynamicField name="*spell" type="textSpell" indexed="true" stored="false" multiValued="true" />
<dynamicField name="*suggest" type="textSuggest" indexed="true" stored="false" multiValued="true" />
<!-- for spell checking -->
<copyField source="*_s" dest="spell"/>
<copyField source="*_sm" dest="spell"/>
<!-- for suggestions -->
<copyField source="*_t" dest="suggest"/>
<copyField source="*_facet" dest="suggest"/>
<copyField source="*_s" dest="suggest"/>
<copyField source="*_sm" dest="suggest"/>
<fieldType name="textSuggest" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.KeywordTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="textSpell" class="solr.TextField" positionIncrementGap="100" >
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldType>
In your solrconfig.xml, add a searchComponent and requestHandler for suggestions
<!-- searchComponent and requestHandler for completions -->
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">mySuggester</str>
<str name="lookupImpl">FuzzyLookupFactory</str>
<str name="suggestAnalyzerFieldType">textSuggest</str>
<str name="buildOnCommit">true</str>
<str name="field">suggest</str>
</lst>
</searchComponent>
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy">
<lst name="defaults">
<str name="suggest">true</str>
<str name="suggest.count">5</str>
<str name="suggest.dictionary">mySuggester</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>
<!-- searchComponent for spellcheck -->
<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
<!-- a spellchecker built from a field of the main index -->
<lst name="spellchecker">
<str name="name">default</str>
<str name="field">spell</str>
<str name="classname">solr.DirectSolrSpellChecker</str>
<!-- the spellcheck distance measure used, the default is the internal levenshtein -->
<str name="distanceMeasure">internal</str>
<!-- minimum accuracy needed to be considered a valid spellcheck suggestion -->
<float name="accuracy">0.5</float>
<!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 -->
<int name="maxEdits">2</int>
<!-- the minimum shared prefix when enumerating terms -->
<int name="minPrefix">1</int>
<!-- maximum number of inspections per result. -->
<int name="maxInspections">5</int>
<!-- minimum length of a query term to be considered for correction -->
<int name="minQueryLength">4</int>
<!-- maximum threshold of documents a query term can appear to be considered for correction -->
<float name="maxQueryFrequency">0.01</float>
<!-- uncomment this to require suggestions to occur in 1% of the documents
<float name="thresholdTokenFrequency">.01</float>
-->
</lst>
</searchComponent>
The engine includes very simple javascript that relies on typeahead.js and Bloodhound.
It adds typeahead behavior to the blacklight search form's query field, populating it with suggestions from the '/suggest' API endpoint that this engine defines.
If you want the default behavior, simply add this to your application.js
//= require blacklight_suggest
If you want to implement your own behaviors, you can use app/assets/javascripts/blacklight_suggest.js as a reference.
Add the typeahead styles to your CSS. This controls how suggestions appear when they're rendered on the page.
@import 'modules/blacklight_suggest';
If you want complete control over the styling of your suggestions, you can include the base styles from typeahead.js by including this in your CSS
@import 'modules/typeahead';
Solr 4 - run rake solr4:config
before rake solr4:start
These tasks are aliases to jettywrapper
start, stop, etc.
$ rake solr4:clean
$ rake solr4:config
$ rake solr4:start
Solr 5
These tasks are aliases to solr_wrapper
start, stop, etc.
$ rake solr5:clean
$ rake solr5:start
$ rake solr5:config
After cloning the repository, cd into the directory and run the following commands.
$ bundle
$ rake ci:all
To test only against solr4, run
$ rake solr4:ci
To test only against solr5, run
$ rake solr5:ci
If you want to run the tests outside of the ci wrapper, simply start your preferred solr version and then run
$ rspec
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/blacklight_suggest. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the Apache 2 License.