ximate 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/fuzzy_search.c CHANGED
@@ -82,7 +82,7 @@ fuzzy_equal (VALUE self, VALUE text, VALUE pattern, VALUE errors_percent)
82
82
  int distance = levenshtein_distance (t, p);
83
83
  // printf ("Allowed errors: %d - Levenshtein's distance: %d\n", errors, distance);
84
84
  if (distance <= errors)
85
- return Qtrue;
85
+ return INT2NUM (errors - distance);
86
86
  return Qfalse;
87
87
  }
88
88
 
data/lib/ximate/search.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  module Ximate
2
2
 
3
3
  DATA = {}
4
- OPTIONS = {:order_by_rank => true, :error_percent => 20, :logger => true}
4
+ OPTIONS = {:order_by_rank => true,
5
+ :match_error_percent => 20,
6
+ :ignore_word_short_than => 2,
7
+ :logger => true,
8
+ :debug => false}
5
9
 
6
10
  def self.included(base)
7
11
  base.extend(Search)
@@ -23,7 +27,7 @@ module Ximate
23
27
  self.to_s.classify.constantize.all.each do |p|
24
28
  p.update_index(locale, &block)
25
29
  end
26
- Rails.logger.info("Build XIMATE hash data for '#{table}' in #{Time.now - now}.") if OPTIONS[:logger]
30
+ puts "\b\b=> Build XIMATE hash data for '#{table}' in #{Time.now - now}." if OPTIONS[:logger]
27
31
  end
28
32
  end
29
33
 
@@ -32,12 +36,22 @@ module Ximate
32
36
 
33
37
  def asearch(pattern)
34
38
  table = self.to_s.underscore.pluralize.to_sym
35
- matches = {}
39
+ matches = {} # {id => rank, id => rank}
40
+ lastsearch = {} # Save last 'e' search for every word in pattern to avoid multi-search of the same word
41
+ pattern.split(' ').each { |w| lastsearch[w] = -1 }
36
42
  DATA[I18n.locale] ||= {}
37
43
  DATA[I18n.locale][table] ||= {}
38
- DATA[I18n.locale][table].each do |word, ids|
39
- if Fuzzy.equal(word, pattern.downcase, OPTIONS[:error_percent])
40
- ids.each {|id, rank| matches[id] = matches[id].to_i + rank}
44
+ DATA[I18n.locale][table].each do |word, ids_ranks|
45
+ pattern.split(' ').each do |w|
46
+ if w.size > OPTIONS[:ignore_word_short_than]
47
+ if e = Fuzzy.equal(word, w.downcase, OPTIONS[:match_error_percent])
48
+ if e > lastsearch[w]
49
+ lastsearch[w] = e
50
+ Rails.logger.debug("XIMATE asearch: '#{word}' match with '#{w}' (e = #{e})") if OPTIONS[:debug]
51
+ ids_ranks.each { |id, rank| matches[id] = matches[id].to_i + (e**rank) }
52
+ end
53
+ end
54
+ end
41
55
  end
42
56
  end
43
57
  return where('1 = 0') if matches.empty?
@@ -45,33 +59,36 @@ module Ximate
45
59
  rel.ranks = matches if OPTIONS[:order_by_rank]
46
60
  rel.where("#{table}.id IN (#{matches.keys.join(',')})")
47
61
  end
62
+
48
63
  end
49
64
 
50
65
 
51
66
  module InstanceMethods
52
67
 
53
- def add_text(text)
54
- @words ||= []
55
- @words += text.to_s.gsub(/<[^>]*>/i, ' ').gsub(/[\.,'":;!\?\(\)]/, ' ').split(' ').map{|word| word.downcase}
68
+ def add_text(text, priority = 1)
69
+ @words ||= {}
70
+ @words[priority] ||= []
71
+ @words[priority] += text.to_s.gsub(/<[^>]*>/i, ' ').gsub(/[\.,'":;!\?\(\)]/, ' ').split(' ').map{|word| word.downcase}.uniq
56
72
  end
57
73
 
58
74
  def update_index(locale = I18n.default_locale, &block)
59
75
  table = self.class.to_s.underscore.pluralize.to_sym
60
76
  remove_index(locale)
61
77
  instance_eval(&block)
62
- @words.each do |word|
63
- ids = (DATA[locale.to_sym][table][word] ||= {})
64
- ids[self.id] ||= 0
65
- ids[self.id] += 1
78
+ @words.each do |priority, words|
79
+ words.each do |word|
80
+ ids_ranks = (DATA[locale.to_sym][table][word] ||= {})
81
+ ids_ranks[self.id] = ids_ranks[self.id].to_i + priority
82
+ end
66
83
  end
67
84
  end
68
85
 
69
86
  def remove_index(locale)
70
87
  table = self.class.to_s.underscore.pluralize.to_sym
71
- @words = []
72
- DATA[locale.to_sym][table].each do |word, ids|
73
- ids.delete(self.id)
74
- DATA[locale.to_sym][table].delete(word) if ids.empty?
88
+ @words = {}
89
+ DATA[locale.to_sym][table].each do |word, ids_ranks|
90
+ ids_ranks.delete(self.id)
91
+ DATA[locale.to_sym][table].delete(word) if ids_ranks.empty?
75
92
  end
76
93
  end
77
94
 
@@ -1,3 +1,3 @@
1
1
  module Ximate
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ximate
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Enrico Pilotto