lib/spontaneous/search/database.rb
# encoding: UTF-8
require 'xapian-fu'
module Spontaneous::Search
class Database
def self.create(index, revision)
db = self.new(index, revision)
db.create
db
end
def initialize(index, revision)
@index, @revision, @database = index, revision, nil
end
def create
FileUtils.mkdir_p(directory)
@database = XapianFu::XapianDb.new(xapian_options.merge({
:create => true,
:overwrite => true
}))
end
def xapian_options
options = { :dir => directory,
:language => @index.language,
:fields => @index.fields,
:spelling => true,
:weights => weighting_proc
}
options[:stemmer] = @index.stemmer unless @index.stemmer.nil?
options[:stopper] = @index.stopper unless @index.stopper.nil?
options
end
def weighting_proc
Proc.new { |key, value, fields| field_weighting(key, fields) }
end
def field_weighting(key, fields)
@weights[key]
end
def database
@database ||= open_database
end
def stemmer
@index.stemmer
end
def stopper
@index.stopper
end
def open_database
XapianFu::XapianDb.new(xapian_options)
end
def add(page)
if @index.include?(page)
@weights = @index.weights(page)
database << @index.indexable_content(page)
end
end
def close
database.flush
end
def search(query, options = {})
xapian_results = database.search(query, options)
autocorrect = options.delete(:autocorrect)
corrected_query = xapian_results.corrected_query
# don't know if this is the right way to deal with the corrected query suggestion
# but I would prefer that any searches act more like google and return a set of
# results for a spelling correction if none have been found with the current query
if autocorrect and xapian_results.empty? and !corrected_query.blank?
xapian_results = database.search(corrected_query, options)
end
Results.new(@index.model, xapian_results, corrected_query)
end
alias_method :<<, :add
def directory
@index.site.revision_dir(@revision) / "indexes" / @index.name
end
end # Database
end