Class: Commendo::RedisBacked::ContentSet

Inherits:
Object
  • Object
show all
Defined in:
lib/commendo/redis-backed/content_set.rb

Constant Summary collapse

SET_TOO_LARGE_FOR_LUA =
999

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key_base, tag_set = nil) ⇒ ContentSet

Returns a new instance of ContentSet.



8
9
10
11
12
# File 'lib/commendo/redis-backed/content_set.rb', line 8

def initialize(key_base, tag_set = nil)
  @redis = Redis.new(host: Commendo.config.host, port: Commendo.config.port, db: Commendo.config.database, timeout: 120)
  @key_base = key_base
  @tag_set = tag_set
end

Instance Attribute Details

#key_baseObject

Returns the value of attribute key_base.



6
7
8
# File 'lib/commendo/redis-backed/content_set.rb', line 6

def key_base
  @key_base
end

#redisObject

Returns the value of attribute redis.



6
7
8
# File 'lib/commendo/redis-backed/content_set.rb', line 6

def redis
  @redis
end

#tag_setObject

Returns the value of attribute tag_set.



6
7
8
# File 'lib/commendo/redis-backed/content_set.rb', line 6

def tag_set
  @tag_set
end

Instance Method Details

#add(resource, *groups) ⇒ Object



24
25
26
27
28
29
30
31
32
# File 'lib/commendo/redis-backed/content_set.rb', line 24

def add(resource, *groups)
  groups.each do |group|
    if group.kind_of?(Array)
      add_single(resource, group[0], group[1])
    else
      add_single(resource, group, 1)
    end
  end
end

#add_and_calculate(resource, *groups) ⇒ Object



39
40
41
42
# File 'lib/commendo/redis-backed/content_set.rb', line 39

def add_and_calculate(resource, *groups)
  add(resource, *groups)
  calculate_similarity_for_resource(resource, 0)
end

#add_by_group(group, *resources) ⇒ Object



14
15
16
17
18
19
20
21
22
# File 'lib/commendo/redis-backed/content_set.rb', line 14

def add_by_group(group, *resources)
  resources.each do |resource|
    if resource.kind_of?(Array)
      add_single(resource[0], group, resource[1])
    else
      add_single(resource, group, 1)
    end
  end
end

#add_single(resource, group, score) ⇒ Object



34
35
36
37
# File 'lib/commendo/redis-backed/content_set.rb', line 34

def add_single(resource, group, score)
  redis.zincrby(group_key(group), score, resource)
  redis.zincrby(resource_key(resource), score, group)
end

#calculate_similarity(threshold = 0) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/commendo/redis-backed/content_set.rb', line 60

def calculate_similarity(threshold = 0)
  #TODO make this use scan for scaling
  keys = redis.keys("#{resource_key_base}:*")
  keys.each_with_index do |key, i|
    resource = key.gsub(/^#{resource_key_base}:/, '')
    similarity_key = similarity_key(resource)
    redis.del(similarity_key)
    yield(key, i, keys.length) if block_given?
    completed = redis.eval(similarity_lua, keys: [key], argv: [tmp_key_base, resource_key_base, similar_key_base, group_key_base, threshold])
    if completed == SET_TOO_LARGE_FOR_LUA
      calculate_similarity_for_key_resource(key, resource, threshold)
    end
  end
end

#calculate_similarity_for_resource(resource, threshold) ⇒ Object



75
76
77
78
# File 'lib/commendo/redis-backed/content_set.rb', line 75

def calculate_similarity_for_resource(resource, threshold)
  key = resource_key(resource)
  calculate_similarity_for_key_resource(key, resource, threshold)
end

#delete(resource) ⇒ Object



48
49
50
51
52
53
54
55
56
# File 'lib/commendo/redis-backed/content_set.rb', line 48

def delete(resource)
  similar = similar_to(resource)
  similar.each do |other_resource|
    redis.zrem(similarity_key(other_resource[:resource]), "#{resource}")
  end
  #TODO delete from groups?
  redis.del(similarity_key(resource))
  redis.del(resource_key(resource))
end

#filtered_similar_to(resource, options = {}) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/commendo/redis-backed/content_set.rb', line 98

def filtered_similar_to(resource, options = {})
  if @tag_set.nil? || (options[:include].nil? && options[:exclude].nil?) || @tag_set.empty?
    return similar_to(resource, options[:limit] || 0)
  else
    similar = similar_to(resource)
    limit = options[:limit] || similar.length
    filtered = []
    similar.each do |s|
      return filtered if filtered.length >= limit
      filtered << s if @tag_set.matches(s[:resource], options[:include], options[:exclude])
    end
    return filtered
  end
end

#groups(resource) ⇒ Object



44
45
46
# File 'lib/commendo/redis-backed/content_set.rb', line 44

def groups(resource)
  redis.zrange(resource_key(resource), 0, -1)
end

#remove_from_groups(resource, *groups) ⇒ Object



117
118
119
120
121
122
123
124
# File 'lib/commendo/redis-backed/content_set.rb', line 117

def remove_from_groups(resource, *groups)
  resource_key = resource_key(resource)
  redis.zrem(resource_key, groups)
  groups.each do |group|
    group_key = group_key(group)
    redis.zrem(group_key, resource)
  end
end

#remove_from_groups_and_calculate(resource, *groups) ⇒ Object



126
127
128
129
# File 'lib/commendo/redis-backed/content_set.rb', line 126

def remove_from_groups_and_calculate(resource, *groups)
  remove_from_groups(resource, *groups)
  calculate_similarity_for_resource(resource, 0)
end

#similar_to(resource, limit = 0) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/commendo/redis-backed/content_set.rb', line 80

def similar_to(resource, limit = 0)
  finish = limit -1
  if resource.kind_of? Array
    keys = resource.map do |res|
      similarity_key(res)
    end
    tmp_key = "#{key_base}:tmp:#{SecureRandom.uuid}"
    redis.zunionstore(tmp_key, keys)
    similar_resources = redis.zrevrange(tmp_key, 0, finish, with_scores: true)
    redis.del(tmp_key)
  else
    similar_resources = redis.zrevrange(similarity_key(resource), 0, finish, with_scores: true)
  end
  similar_resources.map do |resource|
    {resource: resource[0], similarity: resource[1].to_f}
  end
end

#similarity_key(resource) ⇒ Object



113
114
115
# File 'lib/commendo/redis-backed/content_set.rb', line 113

def similarity_key(resource)
  "#{similar_key_base}:#{resource}"
end