Class ActsAsFerret::LocalIndex
In: lib/local_index.rb
Parent: AbstractIndex

Methods

Included Modules

MoreLikeThis::IndexMethods

Public Class methods

[Source]

   # File lib/local_index.rb, line 5
5:     def initialize(index_name)
6:       super
7:       ensure_index_exists
8:     end

Public Instance methods

<<(record, analyzer = nil)

Alias for add

add record to index record may be the full AR object, a Ferret document instance or a Hash

[Source]

     # File lib/local_index.rb, line 103
103:     def add(record, analyzer = nil)
104:       unless Hash === record || Ferret::Document === record
105:         analyzer = record.ferret_analyzer
106:         record = record.to_doc 
107:       end
108:       ferret_index.add_document(record, analyzer)
109:     end

[Source]

    # File lib/local_index.rb, line 58
58:     def bulk_index(class_name, ids, options)
59:       ferret_index.bulk_index(class_name.constantize, ids, options)
60:     end

Closes the underlying index instance

[Source]

    # File lib/local_index.rb, line 36
36:     def close
37:       @ferret_index.close if @ferret_index
38:     rescue StandardError 
39:       # is raised when index already closed
40:     ensure
41:       @ferret_index = nil
42:     end

retrieves stored fields from index definition in case the fields to retrieve haven‘t been specified with the :lazy option

[Source]

     # File lib/local_index.rb, line 166
166:     def determine_stored_fields(options = {})
167:       stored_fields = options[:lazy]
168:       if stored_fields && !(Array === stored_fields)
169:         stored_fields = index_definition[:ferret_fields].select { |field, config| config[:store] == :yes }.map(&:first)
170:       end
171:       logger.debug "stored_fields: #{stored_fields.inspect}"
172:       return stored_fields
173:     end

retrieves the ferret document number of the record with the given key.

[Source]

     # File lib/local_index.rb, line 140
140:     def document_number(key)
141:       docnum = ferret_index.doc_number(key)
142:       # hits = ferret_index.search query_for_record(key)
143:       # return hits.hits.first.doc if hits.total_hits == 1
144:       raise "cannot determine document number for record #{key}" if docnum.nil?
145:       docnum
146:     end

Checks for the presence of a segments file in the index directory Rebuilds the index if none exists.

[Source]

    # File lib/local_index.rb, line 27
27:     def ensure_index_exists
28:       #logger.debug "LocalIndex: ensure_index_exists at #{index_definition[:index_dir]}"
29:       unless File.file? "#{index_definition[:index_dir]}/segments"
30:         ActsAsFerret::ensure_directory(index_definition[:index_dir])
31:         rebuild_index 
32:       end
33:     end

loads data for fields declared as :lazy from the Ferret document

[Source]

     # File lib/local_index.rb, line 176
176:     def extract_stored_fields(doc, stored_fields) 
177:       data = {} 
178:       unless stored_fields.nil?
179:         logger.debug "extracting stored fields #{stored_fields.inspect} from document #{doc[:class_name]} / #{doc[:id]}"
180:         fields = index_definition[:ferret_fields] 
181:         stored_fields.each do |field|
182:           if field_cfg = fields[field]
183:             data[field_cfg[:via]] = doc[field]
184:           end
185:         end
186:         logger.debug "done: #{data.inspect}"
187:       end
188:       return data 
189:     end

The ‘real’ Ferret Index instance

[Source]

    # File lib/local_index.rb, line 17
17:     def ferret_index
18:       ensure_index_exists
19:       returning @ferret_index ||= Ferret::Index::Index.new(index_definition[:ferret]) do
20:         @ferret_index.batch_size = index_definition[:reindex_batch_size]
21:         @ferret_index.logger = logger
22:       end
23:     end

highlight search terms for the record with the given id.

[Source]

     # File lib/local_index.rb, line 118
118:     def highlight(key, query, options = {})
119:       logger.debug("highlight: #{key} query: #{query}")
120:       options.reverse_merge! :num_excerpts => 2, :pre_tag => '<em>', :post_tag => '</em>'
121:       highlights = []
122:       ferret_index.synchronize do
123:         doc_num = document_number(key)
124: 
125:         if options[:field]
126:           highlights << ferret_index.highlight(query, doc_num, options)
127:         else
128:           query = process_query(query) # process only once
129:           index_definition[:ferret_fields].each_pair do |field, config|
130:             next if config[:store] == :no || config[:highlight] == :no
131:             options[:field] = field
132:             highlights << ferret_index.highlight(query, doc_num, options)
133:           end
134:         end
135:       end
136:       return highlights.compact.flatten[0..options[:num_excerpts]-1]
137:     end

Parses the given query string into a Ferret Query object.

[Source]

    # File lib/local_index.rb, line 63
63:     def process_query(query, options = {})
64:       return query unless String === query
65:       ferret_index.synchronize do
66:         if options[:analyzer]
67:           # use per-query analyzer if present
68:           qp = Ferret::QueryParser.new ferret_index.instance_variable_get('@options').merge(options)
69:           reader = ferret_index.reader
70:           qp.fields =
71:               reader.fields unless options[:all_fields] || options[:fields]
72:           qp.tokenized_fields =
73:               reader.tokenized_fields unless options[:tokenized_fields]
74:           return qp.parse query
75:         else
76:           # work around ferret bug in #process_query (doesn't ensure the
77:           # reader is open)
78:           ferret_index.send(:ensure_reader_open)
79:           return ferret_index.process_query(query)
80:         end
81:       end
82:     end

build a ferret query matching only the record with the given id the class name only needs to be given in case of a shared index configuration

[Source]

     # File lib/local_index.rb, line 150
150:     def query_for_record(key)
151:       return Ferret::Search::TermQuery.new(:key, key.to_s)
152:       # if shared?
153:       #   raise InvalidArgumentError.new("shared index needs class_name argument") if class_name.nil?
154:       #   returning bq = Ferret::Search::BooleanQuery.new do
155:       #     bq.add_query(Ferret::Search::TermQuery.new(:id,         id.to_s),    :must)
156:       #     bq.add_query(Ferret::Search::TermQuery.new(:class_name, class_name), :must)
157:       #   end
158:       # else
159:       #   Ferret::Search::TermQuery.new(:id, id.to_s)
160:       # end
161:     end

rebuilds the index from all records of the model classes associated with this index

[Source]

    # File lib/local_index.rb, line 45
45:     def rebuild_index
46:       models = index_definition[:registered_models]
47:       logger.debug "rebuild index with models: #{models.inspect}"
48:       close
49:       index = Ferret::Index::Index.new(index_definition[:ferret].dup.update(:auto_flush  => false, 
50:                                                                             :field_infos => ActsAsFerret::field_infos(index_definition),
51:                                                                             :create      => true))
52:       index.batch_size = index_definition[:reindex_batch_size]
53:       index.logger = logger
54:       index.index_models models
55:       reopen!
56:     end

delete record from index

[Source]

     # File lib/local_index.rb, line 113
113:     def remove(key)
114:       ferret_index.delete key
115:     end

[Source]

    # File lib/local_index.rb, line 10
10:     def reopen!
11:       logger.debug "reopening index at #{index_definition[:ferret][:path]}"
12:       close
13:       ferret_index
14:     end

[Source]

    # File lib/local_index.rb, line 89
89:     def searcher
90:       ferret_index
91:     end

Total number of hits for the given query.

[Source]

    # File lib/local_index.rb, line 85
85:     def total_hits(query, options = {})
86:       ferret_index.search(process_query(query, options), options).total_hits
87:     end

[Validate]