Class: RedisAutocomplete

Inherits:
Object
  • Object
show all
Defined in:
lib/redis_autocomplete.rb

Constant Summary collapse

DEFAULT_DISALLOWED_CHARS =
/[^a-zA-Z0-9_-]/
DEFAULT_TERMINAL =
'+'
DEFAULT_CASE_SENSITIVITY =
true

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ RedisAutocomplete

Returns a new instance of RedisAutocomplete.



10
11
12
13
14
15
16
# File 'lib/redis_autocomplete.rb', line 10

def initialize(opts = {})
  @set_name = opts[:set_name] # optional
  @redis = Redis.new
  @disallowed_chars = opts[:disallowed_chars] || DEFAULT_DISALLOWED_CHARS
  @terminal = opts[:terminal] || DEFAULT_TERMINAL
  @case_sensitive = opts[:case_sensitive].nil? ? DEFAULT_CASE_SENSITIVITY : opts[:case_sensitive]
end

Instance Attribute Details

#redisObject (readonly)

Returns the value of attribute redis.



8
9
10
# File 'lib/redis_autocomplete.rb', line 8

def redis
  @redis
end

#terminalObject (readonly)

Returns the value of attribute terminal.



8
9
10
# File 'lib/redis_autocomplete.rb', line 8

def terminal
  @terminal
end

Instance Method Details

#add_word(word, set_name = nil) ⇒ Object



18
19
20
21
22
23
24
# File 'lib/redis_autocomplete.rb', line 18

def add_word(word, set_name = nil)
  set_name ||= @set_name
  w = word.gsub(@disallowed_chars, '')
  w.downcase! if !@case_sensitive
  (1..(w.length)).each { |i| @redis.zadd(set_name, 0, w.slice(0, i)) }
  @redis.zadd(set_name, 0, "#{w}#{@terminal}")
end

#add_words(words, set_name = nil) ⇒ Object



26
27
28
# File 'lib/redis_autocomplete.rb', line 26

def add_words(words, set_name = nil)
  words.flatten.compact.uniq.each { |word| add_word word, set_name }
end

#remove_word(word, set_name = nil, remove_stems = true) ⇒ Object



30
31
32
33
34
35
# File 'lib/redis_autocomplete.rb', line 30

def remove_word(word, set_name = nil, remove_stems = true)
  set_name ||= @set_name
  @redis.zrem(set_name, "#{word}#{@terminal}")
  # remove_word_stem is inefficient and is best done later on with a cron job
  remove_word_stem(word, set_name) if remove_stems
end

#suggest(prefix, count = 10, set_name = nil) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/redis_autocomplete.rb', line 45

def suggest(prefix, count = 10, set_name = nil)
  set_name ||= @set_name
  results = []
  rangelen = 50 # This is not random, try to get replies < MTU size
  start = @redis.zrank(set_name, prefix)
  return [] if !start
  while results.length != count
    range = @redis.zrange(set_name, start, start+rangelen-1)
    start += rangelen
    break if !range || range.length == 0
    range.each do |entry|
      minlen = [entry.length, prefix.length].min
      if entry.slice(0, minlen) != prefix.slice(0, minlen)
        count = results.count
        break
      end
      if entry[-1] == @terminal and results.length != count
        results << entry.chomp(@terminal)
      end
    end
  end
  return results
end