public
Description: Solr-powered search for Ruby objects
Home | Edit | New

Working with search

Initiating a search

Sunspot searches are initiated with the Sunspot.search method; the arguments are one or more classes to search for, and a block is (optionally) passed to construct the search. In the simplest case, a search for all instances of a class, no block is passed:


search = Sunspot.search(Post)

To search for more than one class at the same time, just pass multiple classes:


search = Sunspot.search(Post, Comment)

Building non-trivial searches using the block DSL is covered in the following chapters; this chapter covers working with the search results.

Getting result objects

The most basic information you want back from a search is the actual result objects; to get these, use the Search#results method. Result objects are instances of the class(es) under search; so, the return value of Sunspot.search(Post, Comment).results will be an array of Post and Comment instances.

Working with WillPaginate

If WillPaginate has been loaded, Sunspot will automatically integrate the results method with it. So, in your template, this will work:


<div class="pagination">
  <%= will_paginate(@search.results) %>
</div>

Working with data directly from Solr

Beyond the values needed to load result instances, Solr provides a few other pieces of information with search results. If the setup for the class of the result has stored fields, Solr will return the stored field values. And if the search being performed includes a keyword component, Solr will return a relevance score. In order to access that information, use the Search#hits method, which returns a collection of Sunspot::Search::Hit objects:


<div class="results>
  <% for hit in @search.hits -%>
    <div class="result">
      <h2><%= hit.stored(:title) %></h2>
      <div class="score"><%= hit.score %></div>
    </div>
  <% end -%>
</div>

Note that when working with Hit objects, the actual object referenced by the Hit is not instantiated unless you call the instance method, which then populates all of the Hit objects for the search in a batch. Clearly, stored fields are primarily useful if they contain enough relevant data that you don’t need to instantiate the result objects.

To get the total number of results in the index matching your search criteria, use the Search#total method.

Working with facets

Facet results are retrieved using the Search#facet method, which takes a single argument: for field and time-range facets, the argument is the name of the field being faceted upon; for query facets, the argument is whatever name you gave the facet when building the search.

All facet objects expose a single method, rows, which returns a collection of FacetRow objects. FacetRows expose two methods: count, which tells the total number of documents matching the search results with the row’s value (or matching the row’s query); and value. For field facets, value is simply the value for the given field associated with that row; for time-range facets, value is a Range object representing the time range associated with that row; and for query facets, value is whatever you defined it as when building the search.

Instantiated facets

For fields set up with the :references option, Sunspot will create instantiated facets in place of normal field facets. Instantiated facet rows respond to the instance method, which loads the instance whose primary key is the value of the facet row. As with hits, instantiated facet instances are lazy-loaded, but when instance is called on any facet row, all the instances for that facet will be batch-loaded.

Here’s an example of working with instantiated facet results:


<div class="facets">
  <h3>Browse by Category</h3>
  <ul class="facet">
    <% for row in @search.facet(:category_ids).rows -%>
      <li><%= link_to(row.instance.name, url_for(:category_id => row.value)) %> (<%= row.count %>)</li>
    <% end -%>
  </ul>
</div>

Last edited by outoftime, Tue Jul 28 04:49:43 -0700 2009
Home | Edit | New
Versions: