ximate 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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