Class: IndexedSearch::Match::DoubleMetaphone

Inherits:
Base
  • Object
show all
Defined in:
lib/indexed_search/match/double_metaphone.rb

Overview

Does a double metaphone algorithm comparison to find words that sound similar. This only works well for English.

You know, they claim this is newer and “better” than the old regular Metaphone, but the keys are way shorter and match tons more words (that aren’t even as similar, kind of like soundex), so rank this just above soundex.

Uses primary_metaphone and secondary_metaphone columns to store values with each entry in the IndexedSearch::Word model.

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#find, find_attributes, #initialize, match_against_term?, #term_matches, #term_non_matches

Constructor Details

This class inherits a constructor from IndexedSearch::Match::Base

Class Method Details

.make_index_value(term) ⇒ Object



63
64
65
# File 'lib/indexed_search/match/double_metaphone.rb', line 63

def self.make_index_value(term)
  Text::Metaphone.double_metaphone(term).collect { |m| m.blank? ? nil : m[0..max_length] }
end

Instance Method Details

#results(do_all = false) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/indexed_search/match/double_metaphone.rb', line 67

def results(do_all=false)
  [].tap do |res|
    if do_all || term_maps[1].present?
      res << IndexedSearch::Match::Result.new(self, term_maps[1], rank_multiplier[0], term_multiplier[0], limit_reduction_factor, type_reduction_factor, 0)
      res << IndexedSearch::Match::Result.new(self, term_maps[1], rank_multiplier[1], term_multiplier[1], limit_reduction_factor, type_reduction_factor, 1)
    end
    if do_all || term_maps[2].present?
      res << IndexedSearch::Match::Result.new(self, term_maps[2], rank_multiplier[2], term_multiplier[2], limit_reduction_factor, type_reduction_factor, 0)
      res << IndexedSearch::Match::Result.new(self, term_maps[2], rank_multiplier[3], term_multiplier[3], limit_reduction_factor, type_reduction_factor, 1)
    end
  end
end

#scopeObject



37
38
39
40
# File 'lib/indexed_search/match/double_metaphone.rb', line 37

def scope
  @scope.where(@scope.arel_table[self.class.matcher_attribute.first].in(term_map.keys).or(
    @scope.arel_table[self.class.matcher_attribute.last].in(term_map.keys)))
end

#term_mapObject



42
43
44
# File 'lib/indexed_search/match/double_metaphone.rb', line 42

def term_map
  term_maps[0]
end

#term_mapsObject



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/indexed_search/match/double_metaphone.rb', line 45

def term_maps
  @term_maps ||= [].tap do |maps|
    # 3 maps: both, primary-only, secondary-only
    3.times { maps << Hash.new { |hash,key| hash[key] = [] } }
    term_matches.each do |term|
      vals = self.class.make_index_value(term)
      unless vals.first.nil?
        maps[0][vals.first] << term
        maps[1][vals.first] << term
      end
      unless vals.last.nil?
        maps[0][vals.last] << term
        maps[2][vals.last] << term
      end
    end
  end
end