lib/picolena/templates/app/models/finder.rb in picolena-0.1.0 vs lib/picolena/templates/app/models/finder.rb in picolena-0.1.1

- old
+ new

@@ -1,71 +1,86 @@ require 'ff' class Finder - attr_reader :index, :query + #FIXME: Should not use all those class methods to access index. + attr_reader :query + + def self.index + # caching index @@index ||= + # causes ferret-0.11.6/lib/ferret/index.rb:768: [BUG] Segmentation fault + Ferret::Index::Index.new(:path => IndexSavePath, :analyzer=>Analyzer) + end + def initialize(raw_query,page=1,results_per_page=ResultsPerPage) query_parser = Ferret::QueryParser.new(:fields => [:content, :file, :basename, :filetype, :date], :or_default => false, :analyzer=>Analyzer) @query = query_parser.parse(convert_to_english(raw_query)) @raw_query= raw_query Finder.ensure_that_index_exists_on_disk - @index = Ferret::Index::Index.new(:path => IndexSavePath, :analyzer=>Analyzer) @per_page=results_per_page @offset=(page.to_i-1)*results_per_page validate_that_index_has_documents end def execute! @matching_documents=[] start=Time.now begin - top_docs=index.search(query, :limit => @per_page, :offset=>@offset) + top_docs=Finder.index.search(query, :limit => @per_page, :offset=>@offset) top_docs.hits.each{|hit| - ferret_doc,score=hit.doc,hit.score + index_id,score=hit.doc,hit.score begin - found_doc=Document.new(index[ferret_doc][:complete_path]) - found_doc.matching_content=index.highlight(query, ferret_doc, + found_doc=Document.new(Finder.index[index_id][:complete_path]) + found_doc.matching_content=Finder.index.highlight(query, index_id, :field => :content, :excerpt_length => 80, :pre_tag => "<<", :post_tag => ">>" ) unless @raw_query=~/^\*+\.\w*$/ found_doc.score=score + found_doc.index_id=index_id @matching_documents<<found_doc rescue Errno::ENOENT #"File has been moved/deleted!" end } @executed=true @time_needed=Time.now-start @total_hits=top_docs.total_hits ensure - index.close + #index.close end end + # Returns true if it has been executed. def executed? @executed end + # To ensure that + # matching_documents + # total_hits + # time_needed + # methods are called only after the index has been searched. [:matching_documents, :total_hits, :time_needed].each{|attribute_name| define_method(attribute_name){ execute! unless executed? instance_variable_get("@#{attribute_name}") } } + # Returns true if index is existing. def self.has_index? index_filename and File.exists?(index_filename) end + # Returns true if there's at least one document indexed. def has_documents? - index.size>0 + Finder.index.size>0 end - - def self.up_to_date? - IndexedDirectories.keys.all?{|dir| File.mtime(index_filename) > File.mtime(dir)} - end + # Returns matching document for any given query, if only + # exactly one document is found. + # Raises otherwise. def matching_document case matching_documents.size when 0 raise IndexError, "No document found" when 1 @@ -75,20 +90,21 @@ end end private - def convert_to_english(str) + # Convert query keywords to english so they can be parsed by Ferret. + def convert_to_english(query) to_en={ /\b#{:AND.l}\b/=>'AND', /\b#{:OR.l}\b/=>'OR', /\b#{:NOT.l}\b/=>'NOT', /(#{:filetype.l}):/=>'filetype:', /#{:content.l}:/ => 'content:', /#{:date.l}:/ => 'date:', /\b#{:LIKE.l}\s+(\S+)/=>'\1~' } - to_en.inject(str){|mem,non_english_to_english_keyword| + to_en.inject(query){|mem,non_english_to_english_keyword| mem.gsub(*non_english_to_english_keyword) } end def self.index_filename