Rails Full Text Search with Ferret
by Jens Kramer
Ferret Library
http://ferret.davebalmain.com
. gem install ferret
the problem?
collected information, and suddenly someone needs to search it!
Ferret structure:
index
documents
fields
Indexing
index = Ferret::Index.new :path => '/tmp/index'
book.each do | book|
index < < {
:content => book.content,
:title => book.title,
:author => book.author
}
end
index.optimize
index.close
Searching
index.search_each('ruby') do |doc_id, score|
doc = index[doc_id]
puts …
end
index.close
note: doc_id changes whenever you change your index, so not a good using it
Query Language
text based, very expressive, very powerful meta language basic queries
- fox
- w?ldcar*
- quick~0.5
- [20050725 20050905]
- “quick|speedy|fast <> fox”
- “quick|fast fox”~2
combined queries
- (quick fast) and fox
- +(qui* fast) -brown +fox
- description:(quick fast) and name:fox
- content:rails title:rails^5 +date: >= 20070101
Ferret Query API
sp_term_q = SpanTermQuery.new(:content, ‘rails’)
sp_first_q ) SpanFirstQuery.new(sp_term_q, 100)
result = index.search(sp_first_q)
Sorting
result = index.search(’ruby’, :sort => ‘date DESC, title’)
sort = Ferret::Search::Sort.new(
Ferret::Search::SortField(:date, :reverse = true, type => :byte)
)
Ferret Browser
- interesting tool…
- comes with the gem
- lets you browse your index
Basic Usage in Rails
class Book < ActiveRecord::Base
acts_as_ferret
end
Book.rebuild.index
results = Book.find_with_ferret …
Field Options
acts_as_ferret(
:fields => {
:title => {:store => :yes, :books => 10}
…
}
:ferret = {
:analyser => GermanSteammingAnalyser.new # custom analyser
}
)
Custom fields
that won’t go into the DB.
acts_as_ferret(
:fields => {
:title => {:store => :yes, :books => 10}
:booktitle => {} # custom!
}
? carefull this fields might be lost when you rebuild index
ActiveRecord Options
allow to modify default active record options
Lazy Options
store only partials not entire results
Multi_Search
you have multiple models, but you’ll need a single search method for an entire app
the only requirement, STORE THE CLASSNAME on the index:
acts_as_ferret(:fields = {…}, :store_classname => true)
(EXAMPLE)
Ferret out there in the wild:
omdb.org
xing.com
blogblogs.com.br
lingr.com
altlaw.org
pertior.com
sachsen-gesetze.de
Further Reading
Ferret Shorcut
Lucene in Action
ferret-talk@rubyforge.org
ferret.davebalmain.com
projects.jkraemer.net/act_as_ferret