Sunspot
Sunspot is a Ruby library for expressive, powerful interaction with the Solr search engine. Sunspot is built on top of the RSolr library, which provides a low-level interface for Solr interaction; Sunspot provides a simple, intuitive, expressive DSL backed by powerful features for indexing objects and searching for them.
Sunspot is designed to be easily plugged in to any ORM, or even non-database-backed objects such as the filesystem.
Where to learn all about Sunspot: The Wiki!
New to Sunspot and using Rails? Check out Adding Sunspot search to Rails in 5 minutes or less.
This README is intended as a quick primer on what Sunspot is capable of; for detailed treatment of Sunspot’s full feature range, check out the wiki: wiki.github.com/outoftime/sunspot
The API documentation is also complete and up-to-date; however, because of the way Sunspot is structured, it’s not the easiest way for new users to get to know the library.
Features:
-
Define indexing strategy for each searchable class using intuitive block-based API
-
Clean separation between keyword-searchable fields and fields for scoping/ordering
-
Define fields based on existing attributes or “virtual fields” for custom indexing
-
Indexes each object’s entire superclass hierarchy, for easy searching for all objects inheriting from a parent class
-
Intuitive DSL for scoping searches, with all the usual boolean operators available
-
Intuitive interface for requesting facets on indexed fields
-
Extensible adapter architecture for easy integration of other ORMs or non-model classes
-
Refine search using field facets, date range facets, or ultra-powerful query facets
-
Full compatibility with will_paginate
-
Ordering by field value, relevance, geographical distance, or random
Installation
gem install sunspot
In order to start the packaged Solr installation, run:
sunspot-solr start -- [-d /path/to/data/directory] [-p port] [-s path/to/solr/home] [--pid-dir=path/to/pid/dir]
If you don’t specify a data directory, your Solr index will be stored in your operating system’s temporary directory.
If you specify a solr home, the directory must contain a conf
directory, which should contain at least schema.xml
and solrconfig.xml
. Be sure to copy the schema.xml
out of the Sunspot gem’s solr/solr/conf
directory. Sunspot relies on the field name patterns defined in the packaged schema.xml
, so those cannot be modified.
You can also run your own instance of Solr wherever you’d like; just copy the solr/config/schema.xml file out of the gem’s solr into your installation. You can change the URL at which Sunspot accesses Solr with:
Sunspot.config.solr.url = 'http://solr.my.host:9818/solr'
Rails Integration
The Sunspot::Rails plugin makes integrating Sunspot into Rails drop-in easy.
gem install sunspot_rails
See the README for that gem or the Sunspot Wiki for more information.
Using Sunspot
Define an index:
class Post
#...
end
Sunspot.setup(Post) do
text :title, :body
string :author_name
integer :blog_id
integer :category_ids
float :average_rating, :using => :ratings_average
time :published_at
string :sort_title do
title.downcase.sub(/^(an?|the)\W+/, ''/) if title = self.title
end
end
See Sunspot.setup for more information.
Note that in order for a class to be searchable, it must have an adapter registered for itself or one of its subclasses. Adapters allow Sunspot to load objects out of persistent storage, and to determine their primary key for indexing. Sunspot::Rails comes with an adapter for ActiveRecord objects, but for other types of models you will need to define your own. See Sunspot::Adapters for more information.
Search for objects:
search = Sunspot.search Post do
keywords 'great pizza'
with :author_name, 'Mark Twain'
with(:blog_id).any_of [2, 14]
with(:category_ids).all_of [4, 10]
with(:published_at).less_than Time.now
any_of do
with(:expired_at).greater_than(Time.now)
with(:expired_at, nil)
end
without :title, 'Bad Title'
without bad_instance # specifically exclude this instance from results
paginate :page => 3, :per_page => 15
order_by :average_rating, :desc
facet :blog_id
end
See Sunspot.search for more information.
Work with search results (Haml for readability):
.facets
ul.blog_facet
- @search.facet(:blog_id).rows.each do |row|
li.facet_row
= link_to(row.instance.name, params.merge(:blog_id => row.value))
%span.count== (#{row.count})
.page_info== Displaying page #{@search.hits.page} of #{@search.hits.per_page} out of #{@search.total} results
- @search.each_hit_with_result do |hit, post|
.search_result
%h3.title
= link_to(h(hit.stored(:title)), post_url(post))
- if hit.score
%span.relevance== (#{hit.score})
%p= hit.highlight(:description).format { |word| "<span class=\"highlight\">#{word}</span>" }
.pagination= will_paginate(search.hits)
About the API documentation
All of the methods documented in the RDoc are considered part of Sunspot’s public API. Methods that are not part of the public API are documented in the code, but excluded from the RDoc. If you find yourself needing to access methods that are not part of the public API in order to do what you need, please contact me so I can rectify the situation!
Dependencies
-
RSolr
-
Java 1.5+
Sunspot has been tested with MRI 1.8.6 and 1.8.7, REE 1.8.6, YARV 1.9.1, and JRuby 1.2.0
Bugs
Please submit bug reports to outoftime.lighthouseapp.com/projects/20339-sunspot
Contribution Guidelines
Contributions are very welcome - both new features, enhancements, and bug fixes. Bug reports with a failing regression test are also lovely. In order to keep the contribution process as organized and smooth as possible, please follow these guidelines:
-
Contributions should be submitted via Sunspot’s Lighthouse account, with an attached git patch. See below for how to create a git patch.
-
Patches should not make any changes to the gemspec task other than adding/removing dependencies (e.g., changing the name, version, email, description, etc.)
-
Patches should not include any changes to the gemspec itself.
-
Document any new methods, options, arguments, etc.
-
Write tests.
-
As much as possible, follow the coding and testing styles you see in existing code. One could accuse me of being nitpicky about this, but consistent code is easier to read, maintain, and enhance.
-
Don’t make any massive changes to the structure of library or test code. If you think something needs a huge refactor or rearrangement, shoot me a message; trying to apply that kind of patch without warning opens the door to a world of conflict hurt.
Here’s how to create a Git patch - assuming you’re pulling from the canonical Sunspot repository at ‘upstream`:
git fetch upstream
git format-patch --stdout upstream/master.. > my-awesome.patch
Help and Support
Ask for help
-
Sunspot Discussion: [email protected] / groups.google.com/group/ruby-sunspot
Tutorials and Articles
-
Full-text search in Rails with Sunspot (Tropical Software Observations)
-
Sunspot Full-text Search for Rails/Ruby (The Rail World)
-
A Few Sunspot Tips (spiral_code)
-
Sunspot: A Solr-Powered Search Engine for Ruby (Linux Magazine)
-
Sunspot Showed Me the Light (ben koonse)
-
rails3 + heroku + sunspot : madness (anhaminha)
-
Using Sunspot for Free-Text Search with Redis (While I Pondered…)
-
Default scope with Sunspot (Cloudspace)
-
Cucumber and Sunspot (opensoul.org)
-
Testing Sunspot with Cucumber (spiral_code)
-
Running cucumber features with sunspot_rails (Kabisa Blog)
-
How To Use Twitter Lists to Determine Influence (Untitled Startup)
-
Sunspot Quickstart (WebSolr)
-
Solr, and Sunspot (YT!)
-
The Saga of the Switch (mrb – includes comparison of Sunspot and Ultrasphinx)
Contributors
-
Mat Brown ([email protected])
-
Peer Allan ([email protected])
-
Dmitriy Dzema ([email protected])
-
Benjamin Krause ([email protected])
-
Marcel de Graaf ([email protected])
-
Brandon Keepers ([email protected])
-
Peter Berkenbosch ([email protected])
-
Brian Atkinson
-
Tom Coleman ([email protected])
-
Matt Mitchell ([email protected])
-
Nathan Beyer ([email protected])
-
Kieran Topping
-
Nicolas Braem ([email protected])
-
Jeremy Ashkenas ([email protected])
-
Dylan Vaughn ([email protected])
License
Sunspot is distributed under the MIT License, copyright © 2008-2009 Mat Brown