summaryrefslogtreecommitdiffstats
path: root/lib/redmine/search.rb
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2014-12-20 08:10:05 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2014-12-20 08:10:05 +0000
commit71172e241169933bbec364afe9268b4b36d9045f (patch)
tree3d90e1dbde3f0671a1efdf741667221e971cc1c6 /lib/redmine/search.rb
parentc53eb532c2545fd26a72e5d6ac2883d410584cc7 (diff)
downloadredmine-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.rb68
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)