redis-textsearch

Full text search with any type of class or data store using Redis

Downloads
22K
Stars
163
Committers
1

= Redis::TextSearch - Use Redis to perform text search from any type of class

This gem implements an extremely fast text search using Redis, based on the patterns from James Gray's {lists and sets in Redis post}[http://blog.grayproductions.net/articles/lists_and_sets_in_redis] as well as Antirez's {text search gist}[http://gist.github.com/120067]. You can use it with any type of class, whether it be ActiveRecord, DataMapper, MongoRecord, or even a class having nothing to do with an ORM.

This is not intended to be the most full-featured text search available. For that, look into {Sphinx}[http://www.sphinxsearch.com/], {Solr}[http://lucene.apache.org/solr/], or {other alternatives}[http://en.wikipedia.org/wiki/Full_text_search#Open_Source_projects]. This gem is designed to (a) be extremely fast and (b) handle any (or multiple) data stores.

The only requirement this gem has is that your class must provide an +id+ instance method which returns the ID for that instance. ActiveRecord, DataMapper, and MongoRecord all have +id+ methods which are known to be suitable. Since "ID" can be any data type, you can even write an +id+ method of your own that just returns a string, or an MD5 of a filename, or something else unique.

== Installation

gem install redis-textsearch

== Initialization

If you're using Rails, config/initializers/redis.rb is a good place for this:

require 'redis'
require 'redis/text_search'
Redis::TextSearch.redis = Redis.new(:host => 'localhost', :port => 6379)

== Example

Model class:

class Post < ActiveRecord::Base
  include Redis::TextSearch

  text_index :title, :minlength => 2
  text_index :tags, :exact => true
  text_index :description, :full => true  # allow full-phrase "Search With Spaces"

  # Using AR callback (you can call update_text_indexes anywhere on your instance)
  after_save do |r|
    r.update_text_indexes
  end
  after_destroy do |r|
    r.delete_text_indexes
  end
end

Create posts:

Post.create(:title => "All About Bacon", :tags => "chef nontechnical")
Post.create(:title => "All About Bacon - Part 2", :tags => "chef nontechnical")
Post.create(:title => "Homemade Belgian Waffles", :tags => "chef nontechnical")
Post.create(:title => "Using Redis with Ruby", :tags => "technical ruby redis")
Post.create(:title => "Installing Redis on Linux", :tags => "technical redis linux")
Post.create(:title => "Chef Deployment Recipes", :tags => "ruby howto chef")

Then search for them:

@posts = Post.text_search('bacon')   # 2 results
@posts = Post.text_search('chef')    # 4 results (tags and title)
@posts = Post.text_search('technical', 'ruby')   # AND search (1 result)
@posts = Post.text_search('chef', :fields => :tags)   # 3 results (only search tags)

You can pass options through to the +find+ method:

@posts = Post.text_search('redis', :order => 'updated_at desc')
@posts = Post.text_search('redis', :select => 'id,title', :limit => 50)

And do pagination (adapted from +will_paginate+):

@posts = Post.text_search('redis', :page => 1, :per_page => 10)
@posts = Post.text_search('redis', :page => 1)  # uses class.per_page like will_paginate

You can also specify specific fields to search as a hash:

@posts = Post.text_search(:tags => 'chef')  # 4 results
@posts = Post.text_search(:tags => ['technical','ruby'])  # AND (1 result)
@posts = Post.text_search(:tags => 'redis', :title => 'linux')  # 1 result
@posts = Post.text_search(:title => 'chef') # 1 result

Note that if you need to pass options to +find+ AND search specific fields, the first hash must be in brackets:

@posts = Post.text_search({:tags => 'chef', :title => 'deployment'},
                          :order => 'updated_at desc')

== Author

Copyright (c) 2009-2010 {Nate Wiger}[http://nate.wiger.org]. All Rights Reserved. Released under the {Artistic License}[http://www.opensource.org/licenses/artistic-license-2.0.php].