Module: ActsAsFerret::FerretFindMethods
- Included in:
- AbstractIndex, MultiIndexBase
- Defined in:
- lib/acts_as_ferret/ferret_find_methods.rb
Overview
Ferret search logic common to single-class indexes, shared indexes and multi indexes.
Instance Method Summary collapse
- #ar_find(q, options = {}, ar_options = {}) ⇒ Object
- #count_records(id_arrays, ar_options = {}) ⇒ Object
- #find_id_model_arrays(q, options) ⇒ Object
-
#find_ids(query, options = {}) ⇒ Object
Queries the Ferret index to retrieve model class, id, score and the values of any fields stored in the index for each hit.
- #find_records(q, options = {}, ar_options = {}) ⇒ Object
- #lazy_find(q, options = {}) ⇒ Object
- #scope_query_to_models(query, models) ⇒ Object
Instance Method Details
#ar_find(q, options = {}, ar_options = {}) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/acts_as_ferret/ferret_find_methods.rb', line 35 def ar_find(q, = {}, = {}) = .dup if [:conditions] or [:order] [:limit] = :all .delete :offset end total_hits, id_arrays = find_id_model_arrays q, logger.debug "now retrieving records from AR with options: #{.inspect}" result = ActsAsFerret::retrieve_records(id_arrays, ) logger.debug "#{result.size} results from AR: #{result.inspect}" # count total_hits via sql when using conditions, multiple models, or when we're called # from an ActiveRecord association. if id_arrays.size > 1 or [:conditions] # chances are the ferret result count is not our total_hits value, so # we correct this here. if [:limit] != :all || [:page] || [:offset] || [:limit] || [:offset] # our ferret result has been limited, so we need to re-run that # search to get the full result set from ferret. new_th, id_arrays = find_id_model_arrays( q, .merge(:limit => :all, :offset => 0) ) # Now ask the database for the total size of the final result set. total_hits = count_records( id_arrays, ) else # what we got from the database is our full result set, so take # it's size total_hits = result.length end end [ total_hits, result ] end |
#count_records(id_arrays, ar_options = {}) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/acts_as_ferret/ferret_find_methods.rb', line 66 def count_records(id_arrays, = {}) = .dup .delete :limit .delete :offset .delete :order .delete :select count = 0 id_arrays.each do |model, id_array| next if id_array.empty? model = model.constantize # merge conditions conditions = ActsAsFerret::conditions_for_model model, [:conditions] [:conditions] = ActsAsFerret::combine_conditions([ "#{model.table_name}.#{model.primary_key} in (?)", id_array.keys ], conditions) [:include] = ActsAsFerret::filter_include_list_for_model(model, [:include]) if [:include] cnt = model.count if cnt.is_a?(ActiveSupport::OrderedHash) # fixes #227 count += cnt.size else count += cnt end end count end |
#find_id_model_arrays(q, options) ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'lib/acts_as_ferret/ferret_find_methods.rb', line 90 def find_id_model_arrays(q, ) id_arrays = {} rank = 0 total_hits = find_ids(q, ) do |model, id, score, data| id_arrays[model] ||= {} id_arrays[model][id] = [ rank += 1, score ] end [total_hits, id_arrays] end |
#find_ids(query, options = {}) ⇒ Object
Queries the Ferret index to retrieve model class, id, score and the values of any fields stored in the index for each hit. If a block is given, these are yielded and the number of total hits is returned. Otherwise [total_hits, result_array] is returned.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/acts_as_ferret/ferret_find_methods.rb', line 104 def find_ids(query, = {}) result = [] stored_fields = determine_stored_fields q = process_query(query, ) q = scope_query_to_models q, [:models] #if shared? # Force q to be encoded as UTF-8 to avoid barfing when unicode passed in. # Was not an issue pre ruby 1.9.x force_encoding method is only available in ruby 1.9.x q_to_s = q.to_s.respond_to?('force_encoding') ? q.to_s.force_encoding('UTF-8') : q logger.debug "query: #{query}\n-->#{q_to_s}" s = searcher total_hits = s.search_each(q, ) do |hit, score| doc = s[hit] model = doc[:class_name] # fetch stored fields if lazy loading data = extract_stored_fields(doc, stored_fields) if block_given? yield model, doc[:id], score, data else result << { :model => model, :id => doc[:id], :score => score, :data => data } end end #logger.debug "id_score_model array: #{result.inspect}" return block_given? ? total_hits : [total_hits, result] end |
#find_records(q, options = {}, ar_options = {}) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/acts_as_ferret/ferret_find_methods.rb', line 6 def find_records(q, = {}, = {}) late_pagination = .delete :late_pagination total_hits, result = if [:lazy] logger.warn "find_options #{} are ignored because :lazy => true" unless .empty? lazy_find q, else ar_find q, , end if late_pagination limit = late_pagination[:limit] offset = late_pagination[:offset] || 0 end_index = limit == :all ? -1 : limit+offset-1 # puts "late pagination: #{offset} : #{end_index}" result = result[offset..end_index] end return [total_hits, result] end |
#lazy_find(q, options = {}) ⇒ Object
24 25 26 27 28 29 30 31 32 33 |
# File 'lib/acts_as_ferret/ferret_find_methods.rb', line 24 def lazy_find(q, = {}) logger.debug "lazy_find: #{q}" result = [] rank = 0 total_hits = find_ids(q, ) do |model, id, score, data| logger.debug "model: #{model}, id: #{id}, data: #{data}" result << FerretResult.new(model, id, score, rank += 1, data) end [ total_hits, result ] end |
#scope_query_to_models(query, models) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/acts_as_ferret/ferret_find_methods.rb', line 132 def scope_query_to_models(query, models) return query if models.nil? or models == :all models = [ models ] if Class === models q = Ferret::Search::BooleanQuery.new q.add_query(query, :must) model_query = Ferret::Search::BooleanQuery.new models.each do |model| model_query.add_query(Ferret::Search::TermQuery.new(:class_name, model.name), :should) end q.add_query(model_query, :must) return q end |