@@ -18,8 +18,6 | |||
|
18 | 18 | class SearchController < ApplicationController |
|
19 | 19 | before_filter :find_optional_project |
|
20 | 20 | |
|
21 | @@search_cache_store ||= ActiveSupport::Cache.lookup_store :memory_store | |
|
22 | ||
|
23 | 21 | def index |
|
24 | 22 | @question = params[:q] || "" |
|
25 | 23 | @question.strip! |
@@ -57,7 +55,7 class SearchController < ApplicationController | |||
|
57 | 55 | |
|
58 | 56 | fetcher = Redmine::Search::Fetcher.new( |
|
59 | 57 | @question, User.current, @scope, projects_to_search, |
|
60 | :all_words => @all_words, :titles_only => @titles_only | |
|
58 | :all_words => @all_words, :titles_only => @titles_only, :cache => params[:page].present? | |
|
61 | 59 | ) |
|
62 | 60 | |
|
63 | 61 | if fetcher.tokens.present? |
@@ -47,6 +47,14 module RedmineApp | |||
|
47 | 47 | # Do not include all helpers |
|
48 | 48 | config.action_controller.include_all_helpers = false |
|
49 | 49 | |
|
50 | # Specific cache for search results, the default file store cache is not | |
|
51 | # a good option as it could grow fast. A memory store (32MB max) is used | |
|
52 | # as the default. If you're running multiple server processes, it's | |
|
53 | # recommended to switch to a shared cache store (eg. mem_cache_store). | |
|
54 | # See http://guides.rubyonrails.org/caching_with_rails.html#cache-stores | |
|
55 | # for more options (same options as config.cache_store). | |
|
56 | config.redmine_search_cache_store = :memory_store | |
|
57 | ||
|
50 | 58 | config.session_store :cookie_store, :key => '_redmine_session' |
|
51 | 59 | |
|
52 | 60 | if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb')) |
@@ -31,6 +31,18 module Redmine | |||
|
31 | 31 | search_type = search_type.to_s |
|
32 | 32 | @@available_search_types << search_type unless @@available_search_types.include?(search_type) |
|
33 | 33 | end |
|
34 | ||
|
35 | # Returns the cache store for search results | |
|
36 | # Can be configured with config.redmine_search_cache_store= in config/application.rb | |
|
37 | def cache_store | |
|
38 | @@cache_store ||= begin | |
|
39 | # if config.search_cache_store was not previously set, a no method error would be raised | |
|
40 | config = Rails.application.config.redmine_search_cache_store rescue :memory_store | |
|
41 | if config | |
|
42 | ActiveSupport::Cache.lookup_store config | |
|
43 | end | |
|
44 | end | |
|
45 | end | |
|
34 | 46 | end |
|
35 | 47 | |
|
36 | 48 | class Fetcher |
@@ -41,6 +53,7 module Redmine | |||
|
41 | 53 | @question = question.strip |
|
42 | 54 | @scope = scope |
|
43 | 55 | @projects = projects |
|
56 | @cache = options.delete(:cache) | |
|
44 | 57 | @options = options |
|
45 | 58 | |
|
46 | 59 | # extract tokens from the question |
@@ -52,10 +65,12 module Redmine | |||
|
52 | 65 | @tokens.slice! 5..-1 |
|
53 | 66 | end |
|
54 | 67 | |
|
68 | # Returns the total result count | |
|
55 | 69 | def result_count |
|
56 | 70 | result_ids.size |
|
57 | 71 | end |
|
58 | 72 | |
|
73 | # Returns the result count by type | |
|
59 | 74 | def result_count_by_type |
|
60 | 75 | ret = Hash.new {|h,k| h[k] = 0} |
|
61 | 76 | result_ids.group_by(&:first).each do |scope, ids| |
@@ -64,6 +79,7 module Redmine | |||
|
64 | 79 | ret |
|
65 | 80 | end |
|
66 | 81 | |
|
82 | # Returns the results for the given offset and limit | |
|
67 | 83 | def results(offset, limit) |
|
68 | 84 | result_ids_to_load = result_ids[offset, limit] || [] |
|
69 | 85 | |
@@ -78,12 +94,31 module Redmine | |||
|
78 | 94 | end.compact |
|
79 | 95 | end |
|
80 | 96 | |
|
97 | # Returns the results ids, sorted by rank | |
|
81 | 98 | def result_ids |
|
82 | @ranks_and_ids ||= load_result_ids | |
|
99 | @ranks_and_ids ||= load_result_ids_from_cache | |
|
83 | 100 | end |
|
84 | 101 | |
|
85 | 102 | private |
|
86 | 103 | |
|
104 | def project_ids | |
|
105 | Array.wrap(@projects).map(&:id) | |
|
106 | end | |
|
107 | ||
|
108 | def load_result_ids_from_cache | |
|
109 | if Redmine::Search.cache_store | |
|
110 | cache_key = ActiveSupport::Cache.expand_cache_key( | |
|
111 | [@question, @user.id, @scope.sort, @options, project_ids.sort] | |
|
112 | ) | |
|
113 | ||
|
114 | Redmine::Search.cache_store.fetch(cache_key, :force => !@cache) do | |
|
115 | load_result_ids | |
|
116 | end | |
|
117 | else | |
|
118 | load_result_ids | |
|
119 | end | |
|
120 | end | |
|
121 | ||
|
87 | 122 | def load_result_ids |
|
88 | 123 | ret = [] |
|
89 | 124 | # get all the results ranks and ids |
@@ -95,6 +130,7 module Redmine | |||
|
95 | 130 | end |
|
96 | 131 | # sort results, higher rank and id first |
|
97 | 132 | ret.sort! {|a,b| b.last <=> a.last} |
|
133 | # only keep ids now that results are sorted | |
|
98 | 134 | ret.map! {|scope, r| [scope, r.last]} |
|
99 | 135 | ret |
|
100 | 136 | end |
General Comments 0
You need to be logged in to leave comments.
Login now