Changeset 9
- Timestamp:
- 03/08/06 23:21:04 (3 years ago)
- Files:
-
- trunk/plugin/acts_as_ferret/lib/acts_as_ferret.rb (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/plugin/acts_as_ferret/lib/acts_as_ferret.rb
r8 r9 120 120 def ferret_indexes; @@ferret_indexes end 121 121 122 @@index_searchers = Hash.new123 def index_searchers; @@index_searchers end124 125 122 # declares a class as ferret-searchable. 126 123 # 127 124 # options are: 128 # The mandatory :fields property names all fields to include in the index. 129 # :index_dir declares the directory where to put the index for this class. 130 # The default is RAILS_ROOT/index/RAILS_ENV/CLASSNAME. 131 # The index directory will be created if it doesn't exist. 132 # 133 # parser_options: 134 # occur_default - declares whether query terms are required by 125 # 126 # fields:: names all fields to include in the index. If not given, 127 # all attributes of the class will be indexed. 128 # 129 # index_dir:: declares the directory where to put the index for this class. 130 # The default is RAILS_ROOT/index/RAILS_ENV/CLASSNAME. 131 # The index directory will be created if it doesn't exist. 132 # 133 # ferret_options may be: 134 # occur_default:: - whether query terms are required by 135 135 # default (the default), or not. Specify one of 136 136 # Ferret::Search::BooleanClause::Occur::MUST or 137 # Ferret::Search::BooleanClause::Occur::SHOULD 138 # analyzer - the analyzer to use for query parsing (default: nil, 139 # wihch means the ferret default Analyzer gets used) 140 def acts_as_ferret(options={}, parser_options={}) 141 configuration = { :index_dir => "#{FerretMixin::Acts::ARFerret::index_dir}/#{self.name}" } 137 # Ferret::Search::BooleanClause::Occur::SHOULD 138 # 139 # analyzer:: the analyzer to use for query parsing (default: nil, 140 # wihch means the ferret default Analyzer gets used) 141 # 142 def acts_as_ferret(options={}, ferret_options={}) 143 configuration = { 144 :fields => nil, 145 :index_dir => "#{FerretMixin::Acts::ARFerret::index_dir}/#{self.name}" 146 } 147 ferret_configuration = { 148 :occur_default => Search::BooleanClause::Occur::MUST, 149 :handle_parse_errors => true, 150 :default_search_field => '*', 151 # :analyzer => Analysis::StandardAnalyzer.new, 152 # :wild_lower => true 153 } 142 154 configuration.update(options) if options.is_a?(Hash) 143 144 parser_configuration = { 145 :occur_default => Search::BooleanClause::Occur::MUST, 146 :analyzer => nil 147 } 148 parser_configuration.update(parser_options) if parser_options.is_a? Hash 155 ferret_configuration.update(ferret_options) if ferret_options.is_a?(Hash) 156 # these properties are somewhat vital to the plugin and shouldn't 157 # be overwritten by the user: 158 ferret_configuration.update( 159 :key => :id, 160 :path => configuration[:index_dir], 161 :auto_flush => true, 162 :create_if_missing => true 163 ) 149 164 150 165 class_eval <<-EOV … … 157 172 cattr_accessor :fields_for_ferret 158 173 cattr_accessor :class_index_dir 159 cattr_accessor : parser_configuration174 cattr_accessor :ferret_configuration 160 175 161 176 @@fields_for_ferret = Array.new 162 177 @@class_index_dir = configuration[:index_dir] 163 @@parser_configuration = parser_configuration 164 165 # TODO: make occur_default configurable 166 def self.query_parser 167 @@query_parser ||= 168 QueryParser.new( fields_for_ferret, 169 parser_configuration ) 170 end 178 @@ferret_configuration = ferret_configuration 171 179 172 180 # private … … 177 185 elsif configuration[:fields].respond_to?(:each) 178 186 configuration[:fields].each do |field| 179 define_to_field_method(field)187 define_to_field_method(field) 180 188 end 181 189 else 182 #need to handle :all case190 @@fields_for_ferret = nil 183 191 end 184 192 EOV … … 188 196 189 197 def rebuild_index 190 index = Ferret::Index::Index.new(:path => class_index_dir, :create => true)198 index = Index::Index.new(:path => class_index_dir, :create => true) 191 199 self.find_all.each { |content| index << content.to_doc } 192 200 logger.debug("Created Ferret index in: #{class_index_dir}") … … 199 207 # as the key. 200 208 def ferret_index 201 ferret_indexes[class_index_dir] ||= 202 Index::Index.new(:key => :id, 203 :path => class_index_dir, 204 :auto_flush => true, 205 :create_if_missing => true) 209 ferret_indexes[class_index_dir] ||= Index::Index.new(ferret_configuration) 206 210 end 207 211 208 # returns the searcher for the index that is used for this class. A209 # new searcher will be opened if the segments file is newer than210 # the existing searcher instance. That way modifications of the index211 # will always be reflected by the searcher.212 # Searcher instances are stored in a hash, where the index directory213 # a searcher is working on is the key.214 def index_searcher215 if searcher = index_searchers[class_index_dir]216 last_index_modification = File.mtime "#{class_index_dir}/segments"217 if last_index_modification > searcher.creation_time218 searcher.close219 index_searchers.delete class_index_dir220 end221 end222 index_searchers[class_index_dir] ||= new_index_searcher223 end224 225 def new_index_searcher226 searcher = Search::IndexSearcher.new(class_index_dir)227 searcher.creation_time = Time.now228 searcher229 end230 231 212 # Finds instances by contents. Terms are ANDed by default, can be circumvented 232 213 # by using OR between terms. … … 235 216 # :num_docs - number of hits to retrieve 236 217 def find_by_contents(q, options = {}) 237 if q.is_a? Search::Query238 query = q239 else240 query = query_parser.parse(q)241 end242 logger.debug "parsed query for <#{q}> : <#{query}>"243 218 id_array = [] 244 hits = index_searcher.search(query, options)219 hits = ferret_index.search(q, options) 245 220 hits.each do |hit, score| 246 id_array << index_searcher.reader.get_document(hit)[:id]221 id_array << ferret_index[hit][:id] 247 222 end 248 223 begin … … 287 262 Document::Field::Index::UNTOKENIZED ) 288 263 # iterate through the fields and add them to the document 289 fields_for_ferret.each do |field| 264 if fields_for_ferret 265 # have user defined fields 266 fields_for_ferret.each do |field| 290 267 doc << self.send("#{field}_to_ferret") 268 end 269 else 270 # take all fields 271 self.attributes.each_pair do |key,val| 272 unless key == :id 273 logger.debug "add field #{key} with value #{val}" 274 doc << Document::Field.new( 275 key, 276 val.to_s, 277 Ferret::Document::Field::Store::NO, 278 Ferret::Document::Field::Index::TOKENIZED) 279 end 280 end 291 281 end 292 282 return doc … … 304 294 end 305 295 306 # add creation time attribute to the IndexSearcher class307 Ferret::Search::IndexSearcher.class_eval do308 attr_accessor :creation_time309 end310 311 296 # END acts_as_ferret.rb 312 297
