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)
- - (Object) 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 = {})
Queries the Ferret index to retrieve model class, id, score and the values of any fields stored in the index for each hit.
- - (Object) find_records(q, options = {}, ar_options = {})
- - (Object) lazy_find(q, options = {})
- - (Object) scope_query_to_models(query, models)
Instance Method Details
- (Object) ar_find(q, options = {}, ar_options = {})
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 |
- (Object) count_records(id_arrays, ar_options = {})
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 |
- (Object) find_id_model_arrays(q, options)
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 |
- (Object) find_ids(query, options = {})
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 |
- (Object) find_records(q, options = {}, ar_options = {})
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 |
- (Object) lazy_find(q, options = {})
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 |
- (Object) scope_query_to_models(query, models)
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 |