diff --git a/lib/mongoid_search/mongoid_search.rb b/lib/mongoid_search/mongoid_search.rb index d70d4a2..1d6687c 100644 --- a/lib/mongoid_search/mongoid_search.rb +++ b/lib/mongoid_search/mongoid_search.rb @@ -45,13 +45,13 @@ def search(query, options={}) def search_without_relevance(query, options={}) return criteria.all if query.blank? && allow_empty_search - criteria.send("#{(options[:match]||self.match).to_s}_in", :_keywords => Util.keywords(query, stem_keywords, ignore_list).map { |q| /#{q}/ }) + criteria.send("#{(options[:match]||self.match).to_s}_in", :_keywords => Util.normalize_keywords(query, stem_keywords, ignore_list).map { |q| /#{q}/ }) end def search_relevant(query, options={}) return criteria.all if query.blank? && allow_empty_search - keywords = Util.keywords(query, stem_keywords, ignore_list) + keywords = Util.normalize_keywords(query, stem_keywords, ignore_list) map = <<-EOS function() { @@ -105,31 +105,9 @@ def index_keywords! end private - - # TODO: This need some refactoring.. def set_keywords self._keywords = self.search_fields.map do |field| - if field.is_a?(Hash) - field.keys.map do |key| - attribute = self.send(key) - unless attribute.blank? - method = field[key] - if attribute.is_a?(Array) - if method.is_a?(Array) - method.map {|m| attribute.map { |a| Util.keywords a.send(m), stem_keywords, ignore_list } } - else - attribute.map(&method).map { |t| Util.keywords t, stem_keywords, ignore_list } - end - else - Util.keywords(attribute.send(method), stem_keywords, ignore_list) - end - end - end - else - value = self[field] - value = value.join(' ') if value.respond_to?(:join) - Util.keywords(value, stem_keywords, ignore_list) if value - end + Util.keywords(self, field, stem_keywords, ignore_list) end.flatten.reject{|k| k.nil? || k.empty?}.uniq.sort end end diff --git a/lib/mongoid_search/util.rb b/lib/mongoid_search/util.rb index b059613..668516a 100644 --- a/lib/mongoid_search/util.rb +++ b/lib/mongoid_search/util.rb @@ -1,6 +1,30 @@ module Util - def self.keywords(text, stem_keywords, ignore_list) + def self.keywords(klass, field, stem_keywords, ignore_list) + if field.is_a?(Hash) + field.keys.map do |key| + attribute = klass.send(key) + unless attribute.blank? + method = field[key] + if attribute.is_a?(Array) + if method.is_a?(Array) + method.map {|m| attribute.map { |a| Util.normalize_keywords a.send(m), stem_keywords, ignore_list } } + else + attribute.map(&method).map { |t| Util.normalize_keywords t, stem_keywords, ignore_list } + end + else + Util.normalize_keywords(attribute.send(method), stem_keywords, ignore_list) + end + end + end + else + value = klass[field] + value = value.join(' ') if value.respond_to?(:join) + Util.normalize_keywords(value, stem_keywords, ignore_list) if value + end + end + + def self.normalize_keywords(text, stem_keywords, ignore_list) return [] if text.blank? text = text.to_s. mb_chars. diff --git a/spec/util_spec.rb b/spec/util_spec.rb index 3e5a7b3..3847e56 100644 --- a/spec/util_spec.rb +++ b/spec/util_spec.rb @@ -3,42 +3,42 @@ describe Util do it "should return an empty array if no text is passed" do - Util.keywords("", false, "").should == [] + Util.normalize_keywords("", false, "").should == [] end it "should return an array of keywords" do - Util.keywords("keyword", false, "").class.should == Array + Util.normalize_keywords("keyword", false, "").class.should == Array end it "should return an array of strings" do - Util.keywords("keyword", false, "").first.class.should == String + Util.normalize_keywords("keyword", false, "").first.class.should == String end it "should remove accents from the text passed" do - Util.keywords("café", false, "").should == ["cafe"] + Util.normalize_keywords("café", false, "").should == ["cafe"] end it "should downcase the text passed" do - Util.keywords("CaFé", false, "").should == ["cafe"] + Util.normalize_keywords("CaFé", false, "").should == ["cafe"] end it "should split whitespaces, hifens, dots, underlines, etc.." do - Util.keywords("CaFé-express.com delicious;come visit, and 'win' an \"iPad\"", false, "").should == ["cafe", "express", "com", "delicious", "come", "visit", "and", "win", "an", "ipad"] + Util.normalize_keywords("CaFé-express.com delicious;come visit, and 'win' an \"iPad\"", false, "").should == ["cafe", "express", "com", "delicious", "come", "visit", "and", "win", "an", "ipad"] end it "should stem keywords" do - Util.keywords("A runner running and eating", true, "").should == ["runner", "run", "and", "eat"] + Util.normalize_keywords("A runner running and eating", true, "").should == ["runner", "run", "and", "eat"] end it "should ignore keywords from ignore list" do - Util.keywords("An amazing awesome runner running and eating", true, YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]).should == ["an", "runner", "run", "and", "eat"] + Util.normalize_keywords("An amazing awesome runner running and eating", true, YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]).should == ["an", "runner", "run", "and", "eat"] end it "should ignore keywords with less than two words" do - Util.keywords("A runner running", false, "").should_not include "a" + Util.normalize_keywords("A runner running", false, "").should_not include "a" end it "should not ignore numbers" do - Util.keywords("Ford T 1908", false, "").should include "1908" + Util.normalize_keywords("Ford T 1908", false, "").should include "1908" end end diff --git a/tasks/mongoid_search.rake b/tasks/mongoid_search.rake index a735ba8..f9dd3bb 100644 --- a/tasks/mongoid_search.rake +++ b/tasks/mongoid_search.rake @@ -1,6 +1,6 @@ namespace :mongoid_search do desc 'Goes through all documents with search enabled and indexes the keywords.' - task :index do + task :index => :environment do Mongoid::Search.classes.each do |klass| Log.silent = ENV['SILENT'] Log.log "\nIndexing documents for #{klass.name}:\n"