Sunspot

outoftime.github.com/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:

Installation

gem install sunspot

Optionally install the packaged Solr installation (recommended for development):

gem install sunspot_solr

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 by setting SOLR_URL in your application's environment, or assigning it to Sunspot's configuration directly:

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, :description, :stored => true
  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' do
    highlight :title, :description
  end
  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
  %h4
    %span.count= pluralize(@search.total, 'result')
    %span.pages Page #{@search.hits.current_page} of #{@search.hits.total_pages} 

- @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

  1. RSolr

  2. 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:

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

Tutorials and Articles

Contributors

License

Sunspot is distributed under the MIT License, copyright © 2008-2009 Mat Brown