diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2007-03-10 13:32:04 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2007-03-10 13:32:04 +0000 |
commit | 8b98ceb92c8fba72315d28c3b7664f481547bf24 (patch) | |
tree | 8d64bdfea3a8d89f2193f983c0d00248058b407b /app | |
parent | 7a20a4d32b718f803aa4e3af286ab6a2275b8b6f (diff) | |
download | redmine-8b98ceb92c8fba72315d28c3b7664f481547bf24.tar.gz redmine-8b98ceb92c8fba72315d28c3b7664f481547bf24.zip |
improved search engine
* it's now possible to search for multiple words ("all words" or "one of the words" options)
* added a fixed limit for result count
git-svn-id: http://redmine.rubyforge.org/svn/trunk@321 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/projects_controller.rb | 24 | ||||
-rw-r--r-- | app/helpers/projects_helper.rb | 12 | ||||
-rw-r--r-- | app/views/projects/search.rhtml | 17 |
3 files changed, 34 insertions, 19 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e2ddd3df5..4a957a9cb 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -540,16 +540,24 @@ class ProjectsController < ApplicationController end
def search
- @token = params[:token]
+ @question = params[:q] || ""
+ @question.strip!
+ @all_words = params[:all_words] || (params[:submit] ? false : true)
@scope = params[:scope] || (params[:submit] ? [] : %w(issues news documents) )
-
- if @token and @token.length > 2
- @token.strip!
- like_token = "%#{@token}%"
+ if !@question.empty?
+ # tokens must be at least 3 character long
+ @tokens = @question.split.uniq.select {|w| w.length > 2 }
+ # no more than 5 tokens to search for
+ @tokens.slice! 5..-1 if @tokens.size > 5
+ # strings used in sql like statement
+ like_tokens = @tokens.collect {|w| "%#{w}%"}
+ operator = @all_words ? " AND " : " OR "
+ limit = 10
@results = []
- @results += @project.issues.find(:all, :include => :author, :conditions => ["issues.subject like ? or issues.description like ?", like_token, like_token] ) if @scope.include? 'issues'
- @results += @project.news.find(:all, :conditions => ["news.title like ? or news.description like ?", like_token, like_token], :include => :author ) if @scope.include? 'news'
- @results += @project.documents.find(:all, :conditions => ["title like ? or description like ?", like_token, like_token] ) if @scope.include? 'documents'
+ @results += @project.issues.find(:all, :limit => limit, :include => :author, :conditions => [ (["(LOWER(issues.subject) like ? OR LOWER(issues.description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'issues'
+ @results += @project.news.find(:all, :limit => limit, :conditions => [ (["(LOWER(news.title) like ? OR LOWER(news.description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort], :include => :author ) if @scope.include? 'news'
+ @results += @project.documents.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'documents'
+ @question = @tokens.join(" ")
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index a6c033d0f..694dd9124 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -16,8 +16,14 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module ProjectsHelper
- def result_overview(text, token)
- match = excerpt(text, token)
- match ? highlight(match, token) : truncate(text, 150)
+
+ def highlight_tokens(text, tokens)
+ return text unless tokens && !tokens.empty?
+ regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE
+ result = ''
+ text.split(regexp).each_with_index do |words, i|
+ result << (i.even? ? (words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', words, :class => 'highlight'))
+ end
+ result
end end diff --git a/app/views/projects/search.rhtml b/app/views/projects/search.rhtml index df95ee3ae..e699d8731 100644 --- a/app/views/projects/search.rhtml +++ b/app/views/projects/search.rhtml @@ -2,10 +2,11 @@ <div class="box">
<% form_tag({:action => 'search', :id => @project}, :method => :get) do %>
-<p><%= text_field_tag 'token', @token, :size => 30 %>
+<p><%= text_field_tag 'q', @question, :size => 30 %>
<%= check_box_tag 'scope[]', 'issues', (@scope.include? 'issues') %> <label><%= l(:label_issue_plural) %></label>
<%= check_box_tag 'scope[]', 'news', (@scope.include? 'news') %> <label><%= l(:label_news_plural) %></label>
-<%= check_box_tag 'scope[]', 'documents', (@scope.include? 'documents') %> <label><%= l(:label_document_plural) %></label></p>
+<%= check_box_tag 'scope[]', 'documents', (@scope.include? 'documents') %> <label><%= l(:label_document_plural) %></label><br />
+<%= check_box_tag 'all_words', 1, @all_words %> <%= l(:label_all_words) %></p>
<%= submit_tag l(:button_submit), :name => 'submit' %>
<% end %>
</div>
@@ -16,16 +17,16 @@ <% @results.each do |e| %>
<li><p>
<% if e.is_a? Issue %>
- <%= link_to "#{e.tracker.name} ##{e.id}", :controller => 'issues', :action => 'show', :id => e %>: <%= highlight(h(e.subject), @token) %><br />
- <%= result_overview(e.description, @token) %><br />
+ <%= link_to "#{e.tracker.name} ##{e.id}", :controller => 'issues', :action => 'show', :id => e %>: <%= highlight_tokens(h(e.subject), @tokens) %><br />
+ <%= highlight_tokens(e.description, @tokens) %><br />
<i><%= e.author.name %>, <%= format_time(e.created_on) %></i>
<% elsif e.is_a? News %>
- <%=l(:label_news)%>: <%= link_to highlight(h(e.title), @token), :controller => 'news', :action => 'show', :id => e %><br />
- <%= result_overview(e.description, @token) %><br />
+ <%=l(:label_news)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'news', :action => 'show', :id => e %><br />
+ <%= highlight_tokens(e.description, @tokens) %><br />
<i><%= e.author.name %>, <%= format_time(e.created_on) %></i>
<% elsif e.is_a? Document %>
- <%=l(:label_document)%>: <%= link_to highlight(h(e.title), @token), :controller => 'documents', :action => 'show', :id => e %><br />
- <%= result_overview(e.description, @token) %><br />
+ <%=l(:label_document)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'documents', :action => 'show', :id => e %><br />
+ <%= highlight_tokens(e.description, @tokens) %><br />
<i><%= format_time(e.created_on) %></i>
<% end %>
</p></li>
|