r1262@monsoon: jk | 2006-09-12 23:02:42 +0200
[acts_as_ferret.git] / lib / multi_index.rb
blobfcd9d9284245c9e7bd1669b1ffa4ce153668012e
1 module FerretMixin
2   module Acts #:nodoc:
3     module ARFerret #:nodoc:
4       # not threadsafe
5       class MultiIndex
6         
7         # todo: check for necessary index rebuilds in this place, too
8         # idea - each class gets a create_reader method that does this
9         def initialize(model_classes, options = {})
10           @model_classes = model_classes
11           @options = { 
12             :default_field => '*',
13             #:analyzer => Ferret::Analysis::WhiteSpaceAnalyzer.new
14             :analyzer => Ferret::Analysis::StandardAnalyzer.new
15           }.update(options)
16         end
17         
18         def search(query, options={})
19           #puts "querystring: #{query.to_s}"
20           query = process_query(query)
21           #puts "parsed query: #{query.to_s}"
22           searcher.search(query, options)
23         end
25         def search_each(query, options = {}, &block)
26           query = process_query(query)
27           searcher.search_each(query, options, &block)
28         end
30         # checks if all our sub-searchers still are up to date
31         def latest?
32           return false unless @reader
33           # segfaults with 0.10.4 --> TODO report as bug @reader.latest?
34           @sub_readers.each do |r| 
35             return false unless r.latest? 
36           end
37           true
38         end
39          
40         def searcher
41           ensure_searcher
42           @searcher
43         end
44         
45         def doc(i)
46           searcher[i]
47         end
48         alias :[] :doc
49         
50         def query_parser
51           ensure_searcher 
52           unless @query_parser
53             @query_parser ||= Ferret::QueryParser.new(@options)
54           end
55           @query_parser.fields = @reader.field_names
56           @query_parser
57         end
58         
59         def process_query(query)
60           query = query_parser.parse(query) if query.is_a?(String)
61           return query
62         end
64         def close
65           @searcher.close if @searcher
66           @reader.close if @reader
67         end
69         protected
71           def ensure_searcher
72             unless latest?
73               @sub_readers = @model_classes.map { |clazz| 
74                 begin
75                   reader = Ferret::Index::IndexReader.new(clazz.class_index_dir)
76                 rescue Exception
77                   puts "error opening #{clazz.class_index_dir}: #{$!}"
78                 end
79                 reader
80               }
81               close
82               @reader = Ferret::Index::IndexReader.new(@sub_readers)
83               @searcher = Ferret::Search::Searcher.new(@reader)
84             end
85           end
87       end # of class MultiIndex
89     end
90   end
91 end