module Sunspot

The Sunspot module provides class-method entry points to most of the functionality provided by the Sunspot library. Internally, the Sunspot singleton class contains a (non-thread-safe!) instance of Sunspot::Session, to which it delegates most of the class methods it exposes. In the method documentation below, this instance is referred to as the “singleton session”.

Though the singleton session provides a convenient entry point to Sunspot, it is by no means required to use the Sunspot class methods. Multiple sessions may be instantiated and used (if you need to connect to multiple Solr instances, for example.)

Note that the configuration of classes for index/search (the setup method) is not session-specific, but rather global.

Constants

IllegalSearchError
NoAdapterError
NoSetupError
NotImplementedError
UnrecognizedFieldError
UnrecognizedRestrictionError
VERSION

Attributes

searchable[R]

Access the list of classes set up to be searched.

session[W]

Clients can inject a session proxy, allowing them to implement custom session-management logic while retaining the Sunspot singleton API as an available interface. The object assigned to this attribute must respond to all of the public methods of the Sunspot::Session class.

Public Class Methods

atomic_update(clazz, updates = {}) click to toggle source

Atomic update object properties on the singleton session.

Parameters

clazz<Class>

the class of the objects to be updated

updates<Hash>

hash of updates where keys are model ids and values are hash with property name/values to be updated

Example

post1, post2 = new Array(2) { Post.create }
Sunspot.atomic_update(Post, post1.id => {title: 'New Title'}, post2.id => {description: 'new description'})

Note that indexed objects won't be reflected in search until a commit is sent - see Sunspot.index! and Sunspot.commit

# File lib/sunspot.rb, line 215
def atomic_update(clazz, updates = {})
  session.atomic_update(clazz, updates)
end
atomic_update!(clazz, updates = {}) click to toggle source

Atomic update object properties on the singleton session.

See: Sunspot.atomic_update and Sunspot.commit

Parameters

clazz<Class>

the class of the objects to be updated

updates<Hash>

hash of updates where keys are model ids and values are hash with property name/values to be updated

# File lib/sunspot.rb, line 229
def atomic_update!(clazz, updates = {})
  session.atomic_update!(clazz, updates)
end
batch(&block) click to toggle source

Process all adds in a batch. Any Sunspot adds initiated inside the block will be sent in bulk when the block finishes. Useful if your application initiates index adds from various places in code as part of a single operation; doing a batch add will give better performance.

Example

Sunspot.batch do
  post = Post.new
  Sunspot.index(post)
  comment = Comment.new
  Sunspot.index(comment)
end

Sunspot will send both the post and the comment in a single request.

# File lib/sunspot.rb, line 534
def batch(&block)
  session.batch(&block)
end
commit(soft_commit = false) click to toggle source

Commits (soft or hard) the singleton session

When documents are added to or removed from Solr, the changes are initially stored in memory, and are not reflected in Solr's existing searcher instance. When a hard commit message is sent, the changes are written to disk, and a new searcher is spawned. Commits are thus fairly expensive, so if your application needs to index several documents as part of a single operation, it is advisable to index them all and then call commit at the end of the operation. Solr 4 introduced the concept of a soft commit which is much faster since it only makes index changes visible while not writing changes to disk. If Solr crashes or there is a loss of power, changes that occurred after the last hard commit will be lost.

Note that Solr can also be configured to automatically perform a commit after either a specified interval after the last change, or after a specified number of documents are added. See wiki.apache.org/solr/SolrConfigXml

# File lib/sunspot.rb, line 252
def commit(soft_commit = false)
  session.commit soft_commit
end
commit_if_delete_dirty(soft_commit = false) click to toggle source

Sends a commit if the session has deletes since the last commit (see delete_dirty?).

# File lib/sunspot.rb, line 571
def commit_if_delete_dirty(soft_commit = false)
  session.commit_if_delete_dirty soft_commit
end
commit_if_dirty(soft_commit = false) click to toggle source

Sends a commit (soft or hard) if the session is dirty (see dirty?).

# File lib/sunspot.rb, line 553
def commit_if_dirty(soft_commit = false)
  session.commit_if_dirty soft_commit
end
config() click to toggle source

Returns the configuration associated with the singleton session. See Sunspot::Configuration for details.

Returns

LightConfig::Configuration

configuration for singleton session

# File lib/sunspot.rb, line 582
def config
  session.config
end
delete_dirty?() click to toggle source

True if documents have been removed since the last commit.

Returns

Boolean

Whether there have been any deletes since the last commit

# File lib/sunspot.rb, line 564
def delete_dirty?
  session.delete_dirty?
end
dirty?() click to toggle source

True if documents have been added, updated, or removed since the last commit.

Returns

Boolean

Whether there have been any updates since the last commit

# File lib/sunspot.rb, line 546
def dirty?
  session.dirty?
end
index(*objects) click to toggle source

Indexes objects on the singleton session.

Parameters

objects…<Object>

objects to index (may pass an array or varargs)

Example

post1, post2 = new Array(2) { Post.create }
Sunspot.index(post1, post2)

Note that indexed objects won't be reflected in search until a commit is sent - see Sunspot.index! and Sunspot.commit

# File lib/sunspot.rb, line 183
def index(*objects)
  session.index(*objects)
end
index!(*objects) click to toggle source

Indexes objects on the singleton session and commits immediately.

See: Sunspot.index and Sunspot.commit

Parameters

objects…<Object>

objects to index (may pass an array or varargs)

# File lib/sunspot.rb, line 195
def index!(*objects)
  session.index!(*objects)
end
more_like_this(object, *types, &block) click to toggle source

Initiate a MoreLikeThis search. MoreLikeThis is a special type of search that finds similar documents using fulltext comparison. The fields to be compared are `text` fields set up with the `:more_like_this` option set to `true`. By default, more like this returns objects of the same type as the object used for comparison, but a list of types can optionally be passed to this method to return similar documents of other types. This will only work for types that have common fields.

The DSL for MoreLikeThis search exposes several methods for setting options specific to this type of search. See the Sunspot::DSL::MoreLikeThis class and the MoreLikeThis documentation on the Solr wiki: wiki.apache.org/solr/MoreLikeThis

MoreLikeThis searches have all of the same scoping, ordering, and faceting functionality as standard searches; the only thing you can't do in a MLT search is fulltext matching (since the MLT itself is a fulltext query).

Example

post = Post.first
Sunspot.more_like_this(post, Post, Page) do
  fields :title, :body
  with(:updated_at).greater_than(1.month.ago)
  facet(:category_ids)
end
# File lib/sunspot.rb, line 418
def more_like_this(object, *types, &block)
  session.more_like_this(object, *types, &block)
end
new_more_like_this(object, *types, &block) click to toggle source
# File lib/sunspot.rb, line 386
def new_more_like_this(object, *types, &block)
  session.new_more_like_this(object, *types, &block)
end
optimize() click to toggle source

Optimizes the index on the singletion session.

Frequently adding and deleting documents to Solr, leaves the index in a fragmented state. The optimize command merges all index segments into a single segment and removes any deleted documents, making it faster to search. Since optimize rebuilds the index from scratch, it takes some time and requires double the space on the hard disk while it's rebuilding. Note that optimize also commits.

# File lib/sunspot.rb, line 264
def optimize
  session.optimize
end
remove(*objects, &block) click to toggle source

Remove objects from the index. Any time an object is destroyed, it must be removed from the index; otherwise, the index will contain broken references to objects that do not exist, which will cause errors when those objects are matched in search results.

If a block is passed, it is evaluated as a search scope; in this way, documents can be removed by an arbitrary query. In this case, the arguments to the method should be the classes to run the query on.

Parameters

objects…<Object>

Objects to remove from the index (may pass an array or varargs)

Example (remove a document)

post.destroy
Sunspot.remove(post)

Example (remove by query)

Sunspot.remove(Post) do
  with(:created_at).less_than(Time.now - 14.days)
end
# File lib/sunspot.rb, line 447
def remove(*objects, &block)
  session.remove(*objects, &block)
end
remove!(*objects, &block) click to toggle source

Remove objects from the index and immediately commit. See Sunspot.remove

Parameters

objects…<Object>

Objects to remove from the index

# File lib/sunspot.rb, line 458
def remove!(*objects, &block)
  session.remove!(*objects, &block)
end
remove_all(*classes) click to toggle source

Remove all objects of the given classes from the index. There isn't much use for this in general operations but it can be useful for maintenance, testing, etc. If no arguments are passed, remove everything from the index.

Parameters

classes…<Class>

classes for which to remove all instances from the index (may pass an array or varargs)

Example

Sunspot.remove_all(Post, Blog)
# File lib/sunspot.rb, line 501
def remove_all(*classes)
  session.remove_all(*classes)
end
remove_all!(*classes) click to toggle source

Remove all objects of the given classes from the index and immediately commit. See Sunspot.remove_all

Parameters

classes…<Class>

classes for which to remove all instances from the index

# File lib/sunspot.rb, line 513
def remove_all!(*classes)
  session.remove_all!(*classes)
end
remove_by_id(clazz, *ids) click to toggle source

Remove an object from the index using its class name and primary key. Useful if you know this information and want to remove an object without instantiating it from persistent storage

Parameters

clazz<Class>

Class of the object, or class name as a string or symbol

id

Primary key of the object. This should be the same id that would be returned by the class's instance adapter.

# File lib/sunspot.rb, line 474
def remove_by_id(clazz, *ids)
  session.remove_by_id(clazz, ids)
end
remove_by_id!(clazz, *ids) click to toggle source

Remove an object by class name and primary key, and immediately commit. See remove_by_id and commit

# File lib/sunspot.rb, line 482
def remove_by_id!(clazz, *ids)
  session.remove_by_id!(clazz, ids)
end
reset!(keep_config = false) click to toggle source

Resets the singleton session. This is useful for clearing out all static data between tests, but probably nowhere else.

Parameters

keep_config<Boolean>

Whether to retain the configuration used by the current singleton session. Default false.

# File lib/sunspot.rb, line 596
def reset!(keep_config = false)
  config =
    if keep_config
      session.config
    else
      Configuration.build
    end
  @session = Session.new(config)
end
setup(clazz, &block) click to toggle source

Configures indexing and search for a given class.

Parameters

clazz<Class>

class to configure

Example

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
Attribute Fields vs. Virtual Fields

Attribute fields call a method on the indexed object and index the return value. All of the fields defined above except for the last one are attribute fields. By default, the field name will also be the attribute used; this can be overriden with the :using option, as in :average_rating above. In that case, the attribute :ratings_average will be indexed with the field name :average_rating.

:sort_title is a virtual field, which evaluates the block inside the context of the instance being indexed, and indexes the value returned by the block. If the block you pass takes an argument, it will be passed the instance rather than being evaluated inside of it; so, the following example is equivalent to the one above (assuming title is public):

Sunspot.setup(Post) do
  string :sort_title do |post|
    post.title.downcase.sub(/^(an?|the)\W+/, ''/) if title = self.title
  end
end
Field Types

The available types are:

  • text

  • string

  • integer

  • float

  • time

  • boolean

Note that the text type behaves quite differently from the others - this is the type that is indexed as fulltext, and is searched using the keywords method inside the search DSL. Text fields cannot have restrictions set on them, nor can they be used in order statements or for facets. All other types are indexed literally, and thus can be used for all of those operations. They will not, however, be searched in fulltext. In this way, Sunspot provides a complete barrier between fulltext fields and value fields.

It is fine to specify a field both as a text field and a string field; internally, the fields will have different names so there is no danger of conflict.

Dynamic Fields

For use cases which have highly dynamic data models (for instance, an open set of key-value pairs attached to a model), it may be useful to defer definition of fields until indexing time. Sunspot exposes dynamic fields, which define a data accessor (either attribute or virtual, see above), which accepts a hash of field names to values. Note that the field names in the hash are internally scoped to the base name of the dynamic field, so any time they are referred to, they are referred to using both the base name and the dynamic (runtime-specified) name.

Dynamic fields are speficied in the setup block using the type name prefixed by dynamic_. For example:

Sunspot.setup(Post) do
  dynamic_string :custom_values do
    key_value_pairs.inject({}) do |hash, key_value_pair|
      hash[key_value_pair.key.to_sym] = key_value_pair.value
    end
  end
end

If you later wanted to facet all of the values for the key “cuisine”, you could issue:

Sunspot.search(Post) do
  dynamic :custom_values do
    facet :cuisine
  end
end

In the documentation, :custom_values is referred to as the “base name” - that is, the one specified statically - and :cuisine is referred to as the dynamic name, which is the part that is specified at indexing time.

# File lib/sunspot.rb, line 164
def setup(clazz, &block)
  Sunspot.searchable << clazz
  Setup.setup(clazz, &block)
end