diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2014-12-20 08:10:05 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2014-12-20 08:10:05 +0000 |
commit | 71172e241169933bbec364afe9268b4b36d9045f (patch) | |
tree | 3d90e1dbde3f0671a1efdf741667221e971cc1c6 /lib/redmine/search.rb | |
parent | c53eb532c2545fd26a72e5d6ac2883d410584cc7 (diff) | |
download | redmine-71172e241169933bbec364afe9268b4b36d9045f.tar.gz redmine-71172e241169933bbec364afe9268b4b36d9045f.zip |
Moved search logic to Redmine::Search (#18631).
git-svn-id: http://svn.redmine.org/redmine/trunk@13769 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'lib/redmine/search.rb')
-rw-r--r-- | lib/redmine/search.rb | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/lib/redmine/search.rb b/lib/redmine/search.rb index 580b1843a..42d3004b2 100644 --- a/lib/redmine/search.rb +++ b/lib/redmine/search.rb @@ -19,7 +19,6 @@ module Redmine module Search mattr_accessor :available_search_types - @@available_search_types = [] class << self @@ -34,6 +33,73 @@ module Redmine end end + class Fetcher + attr_reader :tokens + + def initialize(question, user, scope, projects, options={}) + @user = user + @question = question.strip + @scope = scope + @projects = projects + @options = options + + # extract tokens from the question + # eg. hello "bye bye" => ["hello", "bye bye"] + @tokens = @question.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect {|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')} + # tokens must be at least 2 characters long + @tokens = @tokens.uniq.select {|w| w.length > 1 } + # no more than 5 tokens to search for + @tokens.slice! 5..-1 + end + + def result_count + result_ids.size + end + + def result_count_by_type + ret = Hash.new {|h,k| h[k] = 0} + result_ids.group_by(&:first).each do |scope, ids| + ret[scope] += ids.size + end + ret + end + + def results(offset, limit) + result_ids_to_load = result_ids[offset, limit] || [] + + results_by_scope = Hash.new {|h,k| h[k] = []} + result_ids_to_load.group_by(&:first).each do |scope, scope_and_ids| + klass = scope.singularize.camelcase.constantize + results_by_scope[scope] += klass.search_results_from_ids(scope_and_ids.map(&:last)) + end + + result_ids_to_load.map do |scope, id| + results_by_scope[scope].detect {|record| record.id == id} + end.compact + end + + def result_ids + @ranks_and_ids ||= load_result_ids + end + + private + + def load_result_ids + ret = [] + # get all the results ranks and ids + @scope.each do |scope| + klass = scope.singularize.camelcase.constantize + ranks_and_ids_in_scope = klass.search_result_ranks_and_ids(@tokens, User.current, @projects, @options) + # converts timestamps to integers for faster sort + ret += ranks_and_ids_in_scope.map {|rank, id| [scope, [rank.to_i, id]]} + end + # sort results, higher rank and id first + ret.sort! {|a,b| b.last <=> a.last} + ret.map! {|scope, r| [scope, r.last]} + ret + end + end + module Controller def self.included(base) base.extend(ClassMethods) |