Class: ActsAsFerret::LocalIndex
- Inherits:
-
AbstractIndex
- Object
- AbstractIndex
- ActsAsFerret::LocalIndex
- Includes:
- MoreLikeThis::IndexMethods
- Defined in:
- lib/acts_as_ferret/local_index.rb
Instance Attribute Summary
Attributes inherited from AbstractIndex
#index_definition, #index_name, #logger, #registered_models_config
Instance Method Summary collapse
-
#add(record, analyzer = nil) ⇒ Object
(also: #<<)
add record to index record may be the full AR object, a Ferret document instance or a Hash.
- #bulk_index(class_name, ids, options) ⇒ Object
-
#close ⇒ Object
Closes the underlying index instance.
-
#determine_stored_fields(options = {}) ⇒ Object
retrieves stored fields from index definition in case the fields to retrieve haven’t been specified with the :lazy option.
-
#document_number(key) ⇒ Object
retrieves the ferret document number of the record with the given key.
-
#ensure_index_exists ⇒ Object
Checks for the presence of a segments file in the index directory Rebuilds the index if none exists.
-
#extract_stored_fields(doc, stored_fields) ⇒ Object
loads data for fields declared as :lazy from the Ferret document.
-
#ferret_index ⇒ Object
The ‘real’ Ferret Index instance.
-
#highlight(key, query, options = {}) ⇒ Object
highlight search terms for the record with the given id.
-
#initialize(index_name) ⇒ LocalIndex
constructor
A new instance of LocalIndex.
-
#process_query(query, options = {}) ⇒ Object
Parses the given query string into a Ferret Query object.
-
#query_for_record(key) ⇒ Object
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.
-
#rebuild_index ⇒ Object
rebuilds the index from all records of the model classes associated with this index.
-
#remove(key) ⇒ Object
delete record from index.
- #reopen! ⇒ Object
- #searcher ⇒ Object
-
#total_hits(query, options = {}) ⇒ Object
Total number of hits for the given query.
Methods included from MoreLikeThis::IndexMethods
Methods inherited from AbstractIndex
#change_index_dir, #register_class, #shared?
Methods included from FerretFindMethods
#ar_find, #count_records, #find_id_model_arrays, #find_ids, #find_records, #lazy_find, #scope_query_to_models
Constructor Details
#initialize(index_name) ⇒ LocalIndex
Returns a new instance of LocalIndex.
5 6 7 8 |
# File 'lib/acts_as_ferret/local_index.rb', line 5 def initialize(index_name) super ensure_index_exists end |
Instance Method Details
#add(record, analyzer = nil) ⇒ Object Also known as: <<
add record to index record may be the full AR object, a Ferret document instance or a Hash
100 101 102 103 104 105 106 |
# File 'lib/acts_as_ferret/local_index.rb', line 100 def add(record, analyzer = nil) unless Hash === record || Ferret::Document === record analyzer = record.ferret_analyzer record = record.to_doc end ferret_index.add_document(record, analyzer) end |
#bulk_index(class_name, ids, options) ⇒ Object
58 59 60 |
# File 'lib/acts_as_ferret/local_index.rb', line 58 def bulk_index(class_name, ids, ) ferret_index.bulk_index(class_name.constantize, ids, ) end |
#close ⇒ Object
Closes the underlying index instance
36 37 38 39 40 41 42 |
# File 'lib/acts_as_ferret/local_index.rb', line 36 def close @ferret_index.close if @ferret_index rescue StandardError # is raised when index already closed ensure @ferret_index = nil end |
#determine_stored_fields(options = {}) ⇒ Object
retrieves stored fields from index definition in case the fields to retrieve haven’t been specified with the :lazy option
163 164 165 166 167 168 169 170 |
# File 'lib/acts_as_ferret/local_index.rb', line 163 def determine_stored_fields( = {}) stored_fields = [:lazy] if stored_fields && !(Array === stored_fields) stored_fields = index_definition[:ferret_fields].select { |field, config| config[:store] == :yes }.map(&:first) end logger.debug "stored_fields: #{stored_fields.inspect}" return stored_fields end |
#document_number(key) ⇒ Object
retrieves the ferret document number of the record with the given key.
137 138 139 140 141 142 143 |
# File 'lib/acts_as_ferret/local_index.rb', line 137 def document_number(key) docnum = ferret_index.doc_number(key) # hits = ferret_index.search query_for_record(key) # return hits.hits.first.doc if hits.total_hits == 1 raise "cannot determine document number for record #{key}" if docnum.nil? docnum end |
#ensure_index_exists ⇒ Object
Checks for the presence of a segments file in the index directory Rebuilds the index if none exists.
27 28 29 30 31 32 33 |
# File 'lib/acts_as_ferret/local_index.rb', line 27 def ensure_index_exists #logger.debug "LocalIndex: ensure_index_exists at #{index_definition[:index_dir]}" unless File.file? "#{index_definition[:index_dir]}/segments" ActsAsFerret::ensure_directory(index_definition[:index_dir]) rebuild_index end end |
#extract_stored_fields(doc, stored_fields) ⇒ Object
loads data for fields declared as :lazy from the Ferret document
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/acts_as_ferret/local_index.rb', line 173 def extract_stored_fields(doc, stored_fields) data = {} unless stored_fields.nil? logger.debug "extracting stored fields #{stored_fields.inspect} from document #{doc[:class_name]} / #{doc[:id]}" fields = index_definition[:ferret_fields] stored_fields.each do |field| if field_cfg = fields[field] data[field_cfg[:via]] = doc[field] end end logger.debug "done: #{data.inspect}" end return data end |
#ferret_index ⇒ Object
The ‘real’ Ferret Index instance
17 18 19 20 21 22 23 |
# File 'lib/acts_as_ferret/local_index.rb', line 17 def ferret_index ensure_index_exists (@ferret_index ||= Ferret::Index::Index.new(index_definition[:ferret])).tap do |idx| idx.batch_size = index_definition[:reindex_batch_size] idx.logger = logger end end |
#highlight(key, query, options = {}) ⇒ Object
highlight search terms for the record with the given id.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/acts_as_ferret/local_index.rb', line 115 def highlight(key, query, = {}) logger.debug("highlight: #{key} query: #{query}") .reverse_merge! :num_excerpts => 2, :pre_tag => '<em>', :post_tag => '</em>' highlights = [] ferret_index.synchronize do doc_num = document_number(key) if [:field] highlights << ferret_index.highlight(query, doc_num, ) else query = process_query(query) # process only once index_definition[:ferret_fields].each_pair do |field, config| next if config[:store] == :no || config[:highlight] == :no [:field] = field highlights << ferret_index.highlight(query, doc_num, ) end end end return highlights.compact.flatten[0..[:num_excerpts]-1] end |
#process_query(query, options = {}) ⇒ Object
Parses the given query string into a Ferret Query object.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/acts_as_ferret/local_index.rb', line 63 def process_query(query, = {}) return query unless String === query ferret_index.synchronize do if [:analyzer] # use per-query analyzer if present qp = Ferret::QueryParser.new ferret_index.instance_variable_get('@options').merge() reader = ferret_index.reader qp.fields = reader.fields unless [:all_fields] || [:fields] qp.tokenized_fields = reader.tokenized_fields unless [:tokenized_fields] return qp.parse query else return ferret_index.process_query(query) end end end |
#query_for_record(key) ⇒ Object
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
147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/acts_as_ferret/local_index.rb', line 147 def query_for_record(key) return Ferret::Search::TermQuery.new(:key, key.to_s) # if shared? # raise InvalidArgumentError.new("shared index needs class_name argument") if class_name.nil? # Ferret::Search::BooleanQuery.new.tap do |bq| # bq.add_query(Ferret::Search::TermQuery.new(:id, id.to_s), :must) # bq.add_query(Ferret::Search::TermQuery.new(:class_name, class_name), :must) # end # else # Ferret::Search::TermQuery.new(:id, id.to_s) # end end |
#rebuild_index ⇒ Object
rebuilds the index from all records of the model classes associated with this index
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/acts_as_ferret/local_index.rb', line 45 def rebuild_index models = index_definition[:registered_models] logger.debug "rebuild index with models: #{models.inspect}" close index = Ferret::Index::Index.new(index_definition[:ferret].dup.update(:auto_flush => false, :field_infos => ActsAsFerret::field_infos(index_definition), :create => true)) index.batch_size = index_definition[:reindex_batch_size] index.logger = logger index.index_models models reopen! end |
#remove(key) ⇒ Object
delete record from index
110 111 112 |
# File 'lib/acts_as_ferret/local_index.rb', line 110 def remove(key) ferret_index.delete key end |
#reopen! ⇒ Object
10 11 12 13 14 |
# File 'lib/acts_as_ferret/local_index.rb', line 10 def reopen! logger.debug "reopening index at #{index_definition[:ferret][:path]}" close ferret_index end |
#searcher ⇒ Object
86 87 88 |
# File 'lib/acts_as_ferret/local_index.rb', line 86 def searcher ferret_index end |
#total_hits(query, options = {}) ⇒ Object
Total number of hits for the given query.
82 83 84 |
# File 'lib/acts_as_ferret/local_index.rb', line 82 def total_hits(query, = {}) ferret_index.search(process_query(query, ), ).total_hits end |