| Class | ActsAsFerret::LocalIndex |
| In: |
lib/local_index.rb
|
| Parent: | AbstractIndex |
# File lib/local_index.rb, line 5 5: def initialize(index_name) 6: super 7: ensure_index_exists 8: end
add record to index record may be the full AR object, a Ferret document instance or a Hash
# 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
# 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
# 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
# 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.
# 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.
# 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
# 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
# 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.
# 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.
# 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
# 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
# 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
# File lib/local_index.rb, line 113
113: def remove(key)
114: ferret_index.delete key
115: end
# 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