valkey-objects 0.4.7 → 0.4.9
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +8 -0
- data/Gemfile.lock +25 -0
- data/LICENSE.txt +1 -1
- data/README.md +41 -88
- data/lib/valkey/objects/version.rb +1 -1
- data/lib/valkey/objects.rb +483 -721
- data/lib/valkey/objects.rb~ +10 -0
- metadata +15 -153
- data/valkey-objects.gemspec +0 -49
data/lib/valkey/objects.rb
CHANGED
|
@@ -1,810 +1,572 @@
|
|
|
1
|
-
|
|
1
|
+
require 'redis'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
module ValkeyObjects
|
|
4
|
+
def self.included(base)
|
|
5
|
+
base.extend(ClassMethods)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
def valkey
|
|
10
|
+
@valkey ||= Redis.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def valkey=(client)
|
|
14
|
+
@valkey = client
|
|
15
|
+
end
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
def knn *a
|
|
18
|
+
KNN.new([a].flatten.compact)
|
|
19
|
+
end
|
|
17
20
|
|
|
21
|
+
# Define a value (string) attribute
|
|
22
|
+
def value(name, options = {})
|
|
23
|
+
key_name = options[:key] || name.to_s
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
x.extend VK
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.extended(x)
|
|
26
|
-
##
|
|
27
|
-
# Example:
|
|
28
|
-
# class ExmpleObject
|
|
29
|
-
# include VK
|
|
30
|
-
#
|
|
31
|
-
## Add Object Containers by Value Type:
|
|
32
|
-
# value :myValue
|
|
33
|
-
# counter :myCounter
|
|
34
|
-
# hashkey :myHashKey
|
|
35
|
-
# sortedset :mySortedSet
|
|
36
|
-
# set :mySet
|
|
37
|
-
# queue :myQueue
|
|
38
|
-
# place :myPlace
|
|
39
|
-
# toggle :myToggle
|
|
40
|
-
# ticker :myTicker
|
|
41
|
-
# entry :myEntry
|
|
42
|
-
#
|
|
43
|
-
## Add an Object Container With an Implicit Expiration:
|
|
44
|
-
# value :myExpiringValue, ttl: (seconds to live without interaction)
|
|
45
|
-
#
|
|
46
|
-
# def initialize k
|
|
47
|
-
# @id = k
|
|
48
|
-
# end
|
|
49
|
-
# end
|
|
50
|
-
##
|
|
51
|
-
# Create the Object:
|
|
52
|
-
# @obj = ExampleObject.new('object id...')
|
|
53
|
-
##
|
|
54
|
-
# For all object methods:
|
|
55
|
-
# @obj.myObjectContainer.expire(seconds)
|
|
56
|
-
# @obj.myObjectContainer.delete!
|
|
57
|
-
#
|
|
58
|
-
xx = x.name.gsub("::", "-")
|
|
59
|
-
##
|
|
60
|
-
# Object Method Types:
|
|
61
|
-
##
|
|
62
|
-
# A String Value
|
|
63
|
-
##
|
|
64
|
-
# value :myValue
|
|
65
|
-
# @obj.myValue
|
|
66
|
-
# @obj.myValue.exist?
|
|
67
|
-
# @obj.myValue.value = "my value"
|
|
68
|
-
# @obj.myValue.value => "my value"
|
|
69
|
-
define_method(:value) { |k, h={}| define_method(k.to_sym) { VALUE.new(%[#{xx}:value:#{k}:#{@id}], h) } };
|
|
70
|
-
##
|
|
71
|
-
# A Number Value
|
|
72
|
-
##
|
|
73
|
-
# counter :myCounter
|
|
74
|
-
# @obj.myCounter
|
|
75
|
-
# @obj.myCounter.exist?
|
|
76
|
-
# @obj.myCounter.value = number
|
|
77
|
-
# @obj.myCounter.value => number
|
|
78
|
-
# @obj.myCounter.incr number
|
|
79
|
-
# @obj.myCounter.decr number
|
|
80
|
-
#
|
|
81
|
-
define_method(:counter) { |k, h={}| define_method(k.to_sym) { COUNTER.new(%[#{xx}:counter:#{k}:#{@id}], h); } };
|
|
82
|
-
##
|
|
83
|
-
# An Epoch Value
|
|
84
|
-
##
|
|
85
|
-
# timestamp :myTimestamp
|
|
86
|
-
# @obj.myTimestamp
|
|
87
|
-
# @obj.myTimestamp.exist?
|
|
88
|
-
# @obj.myTimestamp.value!
|
|
89
|
-
# @obj.myTimestamp.value => epoch
|
|
90
|
-
# @obj.myTimestamp.ago => Seconds since epoch
|
|
91
|
-
# @obj.myTimestamp.to_time => Time object
|
|
92
|
-
define_method(:timestamp) { |k, h={}| define_method(k.to_sym) { TIMESTAMP.new(%[#{xx}:timestamp:#{k}:#{@id}], h) } }
|
|
93
|
-
##
|
|
94
|
-
# A Hash Value
|
|
95
|
-
##
|
|
96
|
-
# hashkey :myHashKey
|
|
97
|
-
# @obj.myHashKey
|
|
98
|
-
# @obj.myHashKey[:key] = value
|
|
99
|
-
# @obj.myHashKey[:key] => "value"
|
|
100
|
-
# @obj.myHashKey.update({ key: 'value', ... })
|
|
101
|
-
define_method(:hashkey) { |k, h={}| define_method(k.to_sym) { HASH.new(%[#{xx}:hashkey:#{k}:#{@id}], h); } };
|
|
102
|
-
##
|
|
103
|
-
# A Sorted Set Value
|
|
104
|
-
##
|
|
105
|
-
# sortedset :mySortedSet
|
|
106
|
-
# @obj.mySortedSet
|
|
107
|
-
# @obj.mySortedSet[:key] = value
|
|
108
|
-
# @obj.mySortedSet[:key] => ...
|
|
109
|
-
# @obj.mySortedSet.value { |key, i| ... }
|
|
110
|
-
# @obj.mySortedSet.poke key, number
|
|
111
|
-
#
|
|
112
|
-
define_method(:sortedset) { |k, h={}| define_method(k.to_sym) { SORTEDSET.new(%[#{xx}:sortedset:#{k}:#{@id}], h); } };
|
|
113
|
-
##
|
|
114
|
-
# A Collection of Values
|
|
115
|
-
##
|
|
116
|
-
# set :mySet
|
|
117
|
-
# @obj.mySet
|
|
118
|
-
# @obj.mySet << "x"
|
|
119
|
-
# @obj.myset.rm "x"
|
|
120
|
-
# @obj.mySet & @obj.otherSet
|
|
121
|
-
# @obj.mySet | @obj.otherSet
|
|
122
|
-
# @obj.myset["pattern"]
|
|
123
|
-
# @obj.mySet.value { |key, i| ... }
|
|
124
|
-
#
|
|
125
|
-
define_method(:set) { |k, h={}| define_method(k.to_sym) { SET.new(%[#{xx}:set:#{k}:#{@id}], h); } };
|
|
126
|
-
##
|
|
127
|
-
# A List of Values
|
|
128
|
-
##
|
|
129
|
-
# queue :myQueue
|
|
130
|
-
# @obj.myQueue
|
|
131
|
-
# @obj.myQueue << "x"
|
|
132
|
-
# @obj.myQueue.front => "x" and pop
|
|
133
|
-
# @obj.myQueue.last => last in queue
|
|
134
|
-
# @obj.myQueue.value { |key, i| ... }
|
|
135
|
-
#
|
|
136
|
-
define_method(:queue) { |k, h={}| define_method(k.to_sym) { QUEUE.new(%[#{xx}:queue:#{k}:#{@id}], h); } };
|
|
137
|
-
##
|
|
138
|
-
# A Collection of Places
|
|
139
|
-
##
|
|
140
|
-
# place :myPlace
|
|
141
|
-
# @obj.myPlace
|
|
142
|
-
# @obj.myPlace.add "key", longitude, latitude
|
|
143
|
-
# @obj.myPlace["key"] => { longitude: xx, latitude: yy }
|
|
144
|
-
# @obj.myPlace.distance "key", "other key"
|
|
145
|
-
# @obj.myPlace.radius longitude, latitude, distance
|
|
146
|
-
# @obj.myPlace.value { |key, i| ... }
|
|
147
|
-
#
|
|
148
|
-
define_method(:place) { |k, h={}| define_method(k.to_sym) { PLACE.new(%[#{xx}:place:#{k}:#{@id}], h); } };
|
|
149
|
-
##
|
|
150
|
-
# A Boolean Value
|
|
151
|
-
##
|
|
152
|
-
# toggle :myToggle
|
|
153
|
-
# @obj.myToggle
|
|
154
|
-
# @obj.myToggle.exist?
|
|
155
|
-
# @obj.myToggle.value = bool
|
|
156
|
-
# @obj.myToggle.value => ...
|
|
157
|
-
# @obj.myToggle.value! => value = !value
|
|
158
|
-
#
|
|
159
|
-
define_method(:toggle) { |k, h={}| define_method(k.to_sym) { TOGGLE.new(%[#{xx}:toggle:#{k}:#{@id}], h); } };
|
|
160
|
-
##
|
|
161
|
-
# A Sorted Hash of Values
|
|
162
|
-
##
|
|
163
|
-
# ticker :myTicker
|
|
164
|
-
# @obj.myTicker
|
|
165
|
-
# @obj.myTicker[:key] = value
|
|
166
|
-
# @obj.myTicker[:key] => "value"
|
|
167
|
-
# @obj.myticker.value { |i,e| ... }
|
|
168
|
-
define_method(:ticker) { |k, h={}| define_method(k.to_sym) { SORTEDHASH.new(%[#{xx}:ticker:#{k}:#{@id}], h); } };
|
|
169
|
-
##
|
|
170
|
-
# A List of Hashes
|
|
171
|
-
##
|
|
172
|
-
# entry :myEntry
|
|
173
|
-
# @obj.myEntry
|
|
174
|
-
# @obj.myEntry << { key: 'value', ... }
|
|
175
|
-
# @obj.myEntry.value { |i,e| ... }
|
|
176
|
-
define_method(:entry) { |k, h={}| define_method(k.to_sym) { HASHLIST.new(%[#{xx}:entry:#{k}:#{@id}], h); } };
|
|
177
|
-
##
|
|
178
|
-
# A list of Strings
|
|
179
|
-
##
|
|
180
|
-
# vector :myVector
|
|
181
|
-
# @obj.myVector
|
|
182
|
-
# @obj.myVector << "An Entry of Text."
|
|
183
|
-
# @obj.myVector.value { |i,e| ... }
|
|
184
|
-
# @obj.myvector[0] = "An Entry of Text."
|
|
185
|
-
define_method(:vector) { |k, h={}| define_method(k.to_sym) { VECTOR.new(%[#{xx}:vector:#{k}:#{@id}], h); } };
|
|
186
|
-
##
|
|
187
|
-
# An ordered list of strings.
|
|
188
|
-
##
|
|
189
|
-
# vector :myCorpus
|
|
190
|
-
# @obj.myCorpus
|
|
191
|
-
# @obj.myCorpus.value { |i,e| ... }
|
|
192
|
-
# @obj.myCorpus["An entry"] => 5
|
|
193
|
-
define_method(:corpus) { |k, h={}| define_method(k.to_sym) { CORPUS.new(%[#{xx}:corpus:#{k}:#{@id}], h); } };
|
|
194
|
-
##
|
|
195
|
-
# An ordered list of strings.
|
|
196
|
-
##
|
|
197
|
-
# book :myBook
|
|
198
|
-
# @obj.myBook
|
|
199
|
-
# @obj.myBook.value { |index,entry,embedding| ... }
|
|
200
|
-
# @obj.mybook.near("Some entry") => [...]
|
|
201
|
-
# @obj.myBook["An entry"] => 5
|
|
202
|
-
define_method(:book) { |k, h={}| define_method(k.to_sym) { BOOK.new(%[#{xx}:book:#{k}:#{@id}], h); } };
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
def id
|
|
206
|
-
@id
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
def self.at epoch
|
|
210
|
-
Time.at epoch
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
def self.clock *t
|
|
214
|
-
if t[0]
|
|
215
|
-
Time.now.utc.to_i - t[0].to_i
|
|
216
|
-
else
|
|
217
|
-
Time.now.utc.to_i
|
|
25
|
+
define_method(name) do
|
|
26
|
+
ValkeyObjects::Value.new("#{self.class.name.downcase}:#{@id}:value:#{key_name}", self.class.valkey)
|
|
27
|
+
end
|
|
218
28
|
end
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
29
|
+
|
|
30
|
+
# Define a counter attribute
|
|
31
|
+
def counter(name, options = {})
|
|
32
|
+
key_name = options[:key] || name.to_s
|
|
33
|
+
|
|
34
|
+
define_method(name) do
|
|
35
|
+
ValkeyObjects::Counter.new("#{self.class.name.downcase}:#{@id}:counter:#{key_name}", self.class.valkey)
|
|
36
|
+
end
|
|
224
37
|
end
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
# VK.classify("catagory A", "Catagory B").
|
|
234
|
-
def self.classify(a, b)
|
|
235
|
-
ClassifierReborn::Bayes.new(a, b)
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
def self.threshold n
|
|
239
|
-
@@SENTIMENT_THRESHOLD = n
|
|
240
|
-
end
|
|
241
|
-
##
|
|
242
|
-
# Sentiment Analysis.
|
|
243
|
-
##
|
|
244
|
-
# VK.feels("Some text")
|
|
245
|
-
def self.feels x
|
|
246
|
-
Sentimental.new(threshold: @@SENTIMENT_THRESHOLD).sentiment
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
@@CRi = Hash.new { |h,k| h[k] = CRi.new(k) }
|
|
250
|
-
class CRi
|
|
251
|
-
def initialize k
|
|
252
|
-
@id = k
|
|
253
|
-
@lsi = ClassifierReborn::LSI.new
|
|
38
|
+
|
|
39
|
+
# Define a list attribute
|
|
40
|
+
def list(name, options = {})
|
|
41
|
+
key_name = options[:key] || name.to_s
|
|
42
|
+
|
|
43
|
+
define_method(name) do
|
|
44
|
+
ValkeyObjects::List.new("#{self.class.name.downcase}:#{@id}:list:#{key_name}", self.class.valkey)
|
|
45
|
+
end
|
|
254
46
|
end
|
|
255
|
-
|
|
256
|
-
|
|
47
|
+
|
|
48
|
+
# Define a set attribute
|
|
49
|
+
def set(name, options = {})
|
|
50
|
+
key_name = options[:key] || name.to_s
|
|
51
|
+
|
|
52
|
+
define_method(name) do
|
|
53
|
+
ValkeyObjects::Set.new("#{self.class.name.downcase}:#{@id}:set:#{key_name}", self.class.valkey)
|
|
54
|
+
end
|
|
257
55
|
end
|
|
258
|
-
|
|
259
|
-
|
|
56
|
+
|
|
57
|
+
# Define a hash attribute
|
|
58
|
+
def hash_key(name, options = {})
|
|
59
|
+
key_name = options[:key] || name.to_s
|
|
60
|
+
|
|
61
|
+
define_method(name) do
|
|
62
|
+
ValkeyObjects::HashKey.new("#{self.class.name.downcase}:#{@id}:hash:#{key_name}", self.class.valkey)
|
|
63
|
+
end
|
|
260
64
|
end
|
|
261
|
-
|
|
262
|
-
|
|
65
|
+
|
|
66
|
+
# Define a sorted set attribute
|
|
67
|
+
def sorted_set(name, options = {})
|
|
68
|
+
key_name = options[:key] || name.to_s
|
|
69
|
+
|
|
70
|
+
define_method(name) do
|
|
71
|
+
ValkeyObjects::SortedSet.new("#{self.class.name.downcase}:#{@id}:sorted_set:#{key_name}", self.class.valkey)
|
|
72
|
+
end
|
|
263
73
|
end
|
|
264
74
|
end
|
|
265
|
-
|
|
266
|
-
#
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
75
|
+
|
|
76
|
+
# generic KNN processor
|
|
77
|
+
class KNN
|
|
78
|
+
# Initialize with a collection of strings
|
|
79
|
+
def initialize(collection)
|
|
80
|
+
@collection = collection.flatten.compact
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Find k nearest neighbors to the query string
|
|
84
|
+
# Returns array of hashes with :string and :distance keys
|
|
85
|
+
def hood(query)
|
|
86
|
+
# Calculate distances for all strings
|
|
87
|
+
distances = @collection.map do |str|
|
|
88
|
+
{ string: str, distance: levenshtein_distance(query, str) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Sort by distance (ascending) and take top k
|
|
92
|
+
distances.sort_by { |item| item[:distance] }.take([10, @collection.size].min)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def rank query
|
|
96
|
+
neighbors = hood(query)
|
|
97
|
+
|
|
98
|
+
neighbors.map do |item|
|
|
99
|
+
max_len = [query.length, item[:string].length].max
|
|
100
|
+
similarity = max_len.zero? ? 1.0 : 1.0 - (item[:distance].to_f / max_len)
|
|
101
|
+
dist = levenshtein_distance(item[:string], query)
|
|
102
|
+
{ string: item[:string], similarity: similarity.round(4), distance: dist.round(4) }
|
|
103
|
+
end.sort_by { |h| h[:distance] && -h[:similarity] }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def [] q
|
|
107
|
+
rank(q)[0][:string]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
# Calculate Levenshtein distance between two strings
|
|
113
|
+
def levenshtein_distance(s1, s2)
|
|
114
|
+
return s2.length if s1.empty?
|
|
115
|
+
return s1.length if s2.empty?
|
|
116
|
+
|
|
117
|
+
# Create distance matrix
|
|
118
|
+
d = Array.new(s1.length + 1) { Array.new(s2.length + 1) }
|
|
119
|
+
|
|
120
|
+
# Initialize first row and column
|
|
121
|
+
(0..s1.length).each { |i| d[i][0] = i }
|
|
122
|
+
(0..s2.length).each { |j| d[0][j] = j }
|
|
123
|
+
|
|
124
|
+
# Fill in the rest of the matrix
|
|
125
|
+
(1..s1.length).each do |i|
|
|
126
|
+
(1..s2.length).each do |j|
|
|
127
|
+
cost = s1[i - 1] == s2[j - 1] ? 0 : 1
|
|
128
|
+
|
|
129
|
+
d[i][j] = [
|
|
130
|
+
d[i - 1][j] + 1, # deletion
|
|
131
|
+
d[i][j - 1] + 1, # insertion
|
|
132
|
+
d[i - 1][j - 1] + cost # substitution
|
|
133
|
+
].min
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
d[s1.length][s2.length]
|
|
138
|
+
end
|
|
287
139
|
end
|
|
288
140
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
141
|
+
# Value (String) wrapper
|
|
142
|
+
class Value
|
|
143
|
+
attr_reader :key, :valkey
|
|
144
|
+
|
|
145
|
+
def initialize(key, valkey)
|
|
146
|
+
@key = key
|
|
147
|
+
@valkey = valkey
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def value
|
|
151
|
+
valkey.get(key)
|
|
298
152
|
end
|
|
299
|
-
|
|
300
|
-
|
|
153
|
+
|
|
154
|
+
def value=(val)
|
|
155
|
+
valkey.set(key, val)
|
|
301
156
|
end
|
|
302
|
-
|
|
303
|
-
|
|
157
|
+
|
|
158
|
+
def delete
|
|
159
|
+
valkey.del(key)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def exists?
|
|
163
|
+
valkey.exists?(key)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def expire(seconds)
|
|
167
|
+
valkey.expire(key, seconds)
|
|
304
168
|
end
|
|
305
|
-
def value
|
|
306
|
-
x = VK.redis.call("GET", key);
|
|
307
|
-
if @opts.has_key?(:flush) == true
|
|
308
|
-
delete!
|
|
309
|
-
end
|
|
310
|
-
return x
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
169
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
VK.redis.call("SET", key, "#{VK.clock.to_i}");
|
|
170
|
+
def expireat(unix_timestamp)
|
|
171
|
+
valkey.expireat(key, unix_timestamp)
|
|
317
172
|
end
|
|
318
|
-
|
|
319
|
-
|
|
173
|
+
|
|
174
|
+
def ttl
|
|
175
|
+
valkey.ttl(key)
|
|
320
176
|
end
|
|
321
|
-
|
|
322
|
-
|
|
177
|
+
|
|
178
|
+
def persist
|
|
179
|
+
valkey.persist(key)
|
|
323
180
|
end
|
|
324
|
-
|
|
325
|
-
|
|
181
|
+
|
|
182
|
+
def to_s
|
|
183
|
+
value.to_s
|
|
326
184
|
end
|
|
327
185
|
end
|
|
328
186
|
|
|
329
|
-
|
|
187
|
+
# Counter wrapper
|
|
188
|
+
class Counter
|
|
189
|
+
attr_reader :key, :valkey
|
|
190
|
+
|
|
191
|
+
def initialize(key, valkey)
|
|
192
|
+
@key = key
|
|
193
|
+
@valkey = valkey
|
|
194
|
+
end
|
|
195
|
+
|
|
330
196
|
def value
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
delete!
|
|
334
|
-
end
|
|
335
|
-
return x
|
|
197
|
+
val = valkey.get(key)
|
|
198
|
+
val ? val.to_i : 0
|
|
336
199
|
end
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
def value= x
|
|
341
|
-
VK.redis.call("SET", key, "#{x.to_s}")
|
|
200
|
+
|
|
201
|
+
def increment(by = 1)
|
|
202
|
+
valkey.incrby(key, by)
|
|
342
203
|
end
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
else
|
|
347
|
-
self.value = true
|
|
348
|
-
end
|
|
204
|
+
|
|
205
|
+
def decrement(by = 1)
|
|
206
|
+
valkey.decrby(key, by)
|
|
349
207
|
end
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
def value
|
|
354
|
-
x = VK.redis.call("GET", key)
|
|
355
|
-
if @opts.has_key?(:flush) == true
|
|
356
|
-
delete!
|
|
357
|
-
end
|
|
358
|
-
return x
|
|
208
|
+
|
|
209
|
+
def reset
|
|
210
|
+
valkey.set(key, 0)
|
|
359
211
|
end
|
|
360
|
-
|
|
361
|
-
|
|
212
|
+
|
|
213
|
+
def delete
|
|
214
|
+
valkey.del(key)
|
|
362
215
|
end
|
|
363
|
-
|
|
364
|
-
|
|
216
|
+
|
|
217
|
+
def expire(seconds)
|
|
218
|
+
valkey.expire(key, seconds)
|
|
365
219
|
end
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
b.call(m)
|
|
370
|
-
else
|
|
371
|
-
return m
|
|
372
|
-
end
|
|
220
|
+
|
|
221
|
+
def expireat(unix_timestamp)
|
|
222
|
+
valkey.expireat(key, unix_timestamp)
|
|
373
223
|
end
|
|
374
|
-
end
|
|
375
224
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
def value &b
|
|
379
|
-
a = []
|
|
380
|
-
VK.redis.call("LRANGE", key, 0, -1).each_with_index { |e, i|
|
|
381
|
-
if block_given?
|
|
382
|
-
a << b.call(i, VK.redis.call("GET", e))
|
|
383
|
-
else
|
|
384
|
-
a << VK.redis.call("GET", e)
|
|
385
|
-
end
|
|
386
|
-
if @opts.has_key?(:flush) == true
|
|
387
|
-
VK.redis.call("DEL", e);
|
|
388
|
-
end
|
|
389
|
-
}
|
|
390
|
-
if @opts.has_key?(:flush) == true
|
|
391
|
-
delete!
|
|
392
|
-
end
|
|
393
|
-
return a
|
|
394
|
-
end
|
|
395
|
-
def [] k
|
|
396
|
-
VK.redis.call("GET", "#{@key}-#{k}");
|
|
397
|
-
end
|
|
398
|
-
def << i
|
|
399
|
-
kk = %[#{@key}-#{VK.redis.call("LLEN",@key)}]
|
|
400
|
-
VK.redis.call("SET", kk, i);
|
|
401
|
-
VK.redis.call("RPUSH", key, kk)
|
|
402
|
-
end
|
|
403
|
-
def []= k,v
|
|
404
|
-
kk = %[#{@key}-#{k}]
|
|
405
|
-
VK.redis.call("SET", kk, v)
|
|
406
|
-
VK.redis.call("RPUSH", key, kk);
|
|
407
|
-
end
|
|
408
|
-
def nearest p
|
|
409
|
-
h = {}
|
|
410
|
-
value { |i,v|
|
|
411
|
-
h[i] = {
|
|
412
|
-
value: v,
|
|
413
|
-
levenshtein: p.levenshtein_similar(v),
|
|
414
|
-
damerau: p.damerau_levenshtein_similar(v),
|
|
415
|
-
hamming: p.hamming_similar(v),
|
|
416
|
-
distance: p.pair_distance_similar(v),
|
|
417
|
-
subsequence: p.longest_subsequence_similar(v),
|
|
418
|
-
substring: p.longest_substring_similar(v),
|
|
419
|
-
jaro: p.jaro_similar(v),
|
|
420
|
-
winkler: p.jarowinkler_similar(v)
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
return h
|
|
424
|
-
end
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
class COUNTER < O
|
|
428
|
-
def incr n
|
|
429
|
-
VK.redis.call("SET", @key, value + n.to_f)
|
|
225
|
+
def ttl
|
|
226
|
+
valkey.ttl(key)
|
|
430
227
|
end
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
def value
|
|
435
|
-
x = VK.redis.call("GET", @key).to_f
|
|
436
|
-
if @opts.has_key?(:flush) == true
|
|
437
|
-
delete!
|
|
438
|
-
end
|
|
439
|
-
return x
|
|
228
|
+
|
|
229
|
+
def persist
|
|
230
|
+
valkey.persist(key)
|
|
440
231
|
end
|
|
441
|
-
|
|
442
|
-
|
|
232
|
+
|
|
233
|
+
def to_i
|
|
234
|
+
value.to_i
|
|
443
235
|
end
|
|
444
|
-
def exist?
|
|
445
|
-
VK.redis.call("GET", @key) ? true : false
|
|
446
|
-
end
|
|
447
236
|
end
|
|
448
237
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
238
|
+
# List wrapper
|
|
239
|
+
class List
|
|
240
|
+
include Enumerable
|
|
241
|
+
attr_reader :key, :valkey
|
|
242
|
+
|
|
243
|
+
def initialize(key, valkey)
|
|
244
|
+
@key = key
|
|
245
|
+
@valkey = valkey
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def <<(value)
|
|
249
|
+
valkey.rpush(key, value)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def push(*values)
|
|
253
|
+
valkey.rpush(key, values)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def unshift(*values)
|
|
257
|
+
valkey.lpush(key, values.reverse)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def pop
|
|
261
|
+
valkey.rpop(key)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def shift
|
|
265
|
+
valkey.lpop(key)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def [](index)
|
|
269
|
+
valkey.lindex(key, index)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def []=(index, value)
|
|
273
|
+
valkey.lset(key, index, value)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def length
|
|
277
|
+
valkey.llen(key)
|
|
278
|
+
end
|
|
279
|
+
alias_method :size, :length
|
|
280
|
+
|
|
281
|
+
def range(start_idx, end_idx)
|
|
282
|
+
valkey.lrange(key, start_idx, end_idx)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def values
|
|
286
|
+
range(0, -1)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def each(&block)
|
|
290
|
+
values.each(&block)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def expire(seconds)
|
|
294
|
+
valkey.expire(key, seconds)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def expireat(unix_timestamp)
|
|
298
|
+
valkey.expireat(key, unix_timestamp)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def ttl
|
|
302
|
+
valkey.ttl(key)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def persist
|
|
306
|
+
valkey.persist(key)
|
|
452
307
|
end
|
|
453
|
-
|
|
454
|
-
|
|
308
|
+
|
|
309
|
+
### KNN ###
|
|
310
|
+
def knn
|
|
311
|
+
KNN.new(values)
|
|
455
312
|
end
|
|
456
|
-
|
|
457
|
-
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def clear
|
|
316
|
+
valkey.del(key)
|
|
458
317
|
end
|
|
459
|
-
|
|
460
|
-
|
|
318
|
+
|
|
319
|
+
def delete
|
|
320
|
+
clear
|
|
461
321
|
end
|
|
462
322
|
end
|
|
463
323
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
324
|
+
# Set wrapper
|
|
325
|
+
class Set
|
|
326
|
+
include Enumerable
|
|
327
|
+
attr_reader :key, :valkey
|
|
328
|
+
|
|
329
|
+
def initialize(key, valkey)
|
|
330
|
+
@key = key
|
|
331
|
+
@valkey = valkey
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def add(value)
|
|
335
|
+
valkey.sadd(key, value)
|
|
336
|
+
end
|
|
337
|
+
alias_method :<<, :add
|
|
338
|
+
|
|
339
|
+
def remove(value)
|
|
340
|
+
valkey.srem(key, value)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def member?(value)
|
|
344
|
+
valkey.sismember(key, value)
|
|
345
|
+
end
|
|
346
|
+
alias_method :include?, :member?
|
|
347
|
+
|
|
348
|
+
def members
|
|
349
|
+
valkey.smembers(key)
|
|
350
|
+
end
|
|
351
|
+
alias_method :to_a, :members
|
|
352
|
+
|
|
353
|
+
def size
|
|
354
|
+
valkey.scard(key)
|
|
355
|
+
end
|
|
356
|
+
alias_method :length, :size
|
|
357
|
+
|
|
358
|
+
def each(&block)
|
|
359
|
+
members.each(&block)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def expire(seconds)
|
|
363
|
+
valkey.expire(key, seconds)
|
|
470
364
|
end
|
|
471
|
-
|
|
472
|
-
|
|
365
|
+
|
|
366
|
+
def expireat(unix_timestamp)
|
|
367
|
+
valkey.expireat(key, unix_timestamp)
|
|
473
368
|
end
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
369
|
+
|
|
370
|
+
def ttl
|
|
371
|
+
valkey.ttl(key)
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def persist
|
|
375
|
+
valkey.persist(key)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
### KNN ###
|
|
379
|
+
def knn
|
|
380
|
+
KNN.new(members)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def clear
|
|
384
|
+
valkey.del(key)
|
|
479
385
|
end
|
|
480
|
-
|
|
481
|
-
|
|
386
|
+
|
|
387
|
+
def delete
|
|
388
|
+
clear
|
|
482
389
|
end
|
|
483
390
|
end
|
|
484
391
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
392
|
+
# Hash wrapper
|
|
393
|
+
class HashKey
|
|
394
|
+
include Enumerable
|
|
395
|
+
attr_reader :key, :valkey
|
|
396
|
+
|
|
397
|
+
def initialize(key, valkey)
|
|
398
|
+
@key = key
|
|
399
|
+
@valkey = valkey
|
|
491
400
|
end
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return h
|
|
401
|
+
|
|
402
|
+
def [](field)
|
|
403
|
+
valkey.hget(key, field)
|
|
496
404
|
end
|
|
497
|
-
|
|
498
|
-
|
|
405
|
+
|
|
406
|
+
def []=(field, value)
|
|
407
|
+
valkey.hset(key, field, value)
|
|
499
408
|
end
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
def poke k, n
|
|
504
|
-
VK.redis.call("ZINCRBY", key, n.to_f, k);
|
|
409
|
+
|
|
410
|
+
def fetch(field, default = nil)
|
|
411
|
+
valkey.hget(key, field) || default
|
|
505
412
|
end
|
|
506
|
-
end
|
|
507
413
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
a = Set.new
|
|
511
|
-
VK.redis.call("SMEMBERS", key).each_with_index { |e, i|
|
|
512
|
-
if block_given?
|
|
513
|
-
a << b.call(i, e)
|
|
514
|
-
else
|
|
515
|
-
a << e
|
|
516
|
-
end
|
|
517
|
-
}
|
|
518
|
-
if @opts.has_key?(:flush) == true
|
|
519
|
-
delete!
|
|
520
|
-
end
|
|
521
|
-
return a
|
|
414
|
+
def delete(field)
|
|
415
|
+
valkey.hdel(key, field)
|
|
522
416
|
end
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
else
|
|
527
|
-
return true
|
|
528
|
-
end
|
|
417
|
+
|
|
418
|
+
def key?(field)
|
|
419
|
+
valkey.hexists(key, field)
|
|
529
420
|
end
|
|
530
|
-
|
|
531
|
-
|
|
421
|
+
alias_method :has_key?, :key?
|
|
422
|
+
|
|
423
|
+
def keys
|
|
424
|
+
valkey.hkeys(key)
|
|
532
425
|
end
|
|
533
|
-
|
|
534
|
-
|
|
426
|
+
|
|
427
|
+
def values
|
|
428
|
+
valkey.hvals(key)
|
|
535
429
|
end
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
def & k
|
|
540
|
-
VK.redis.call("SINTER", key, k.key)
|
|
430
|
+
|
|
431
|
+
def all
|
|
432
|
+
valkey.hgetall(key)
|
|
541
433
|
end
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
r, h = Regexp.new(k), {}
|
|
547
|
-
VK.redis.call("SMEMBERS", key).each { |e| if m = r.match(e); h[e] = m; end; }
|
|
548
|
-
return h
|
|
434
|
+
alias_method :to_h, :all
|
|
435
|
+
|
|
436
|
+
def size
|
|
437
|
+
valkey.hlen(key)
|
|
549
438
|
end
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
else
|
|
559
|
-
a << e
|
|
560
|
-
end
|
|
561
|
-
};
|
|
562
|
-
if @opts.has_key?(:flush) == true
|
|
563
|
-
delete!
|
|
564
|
-
end
|
|
565
|
-
return a
|
|
439
|
+
alias_method :length, :size
|
|
440
|
+
|
|
441
|
+
def expire(seconds)
|
|
442
|
+
valkey.expire(key, seconds)
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def expireat(unix_timestamp)
|
|
446
|
+
valkey.expireat(key, unix_timestamp)
|
|
566
447
|
end
|
|
567
|
-
|
|
568
|
-
|
|
448
|
+
|
|
449
|
+
def ttl
|
|
450
|
+
valkey.ttl(key)
|
|
569
451
|
end
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
452
|
+
|
|
453
|
+
def persist
|
|
454
|
+
valkey.persist(key)
|
|
573
455
|
end
|
|
574
|
-
|
|
575
|
-
|
|
456
|
+
|
|
457
|
+
def each(&block)
|
|
458
|
+
all.each(&block)
|
|
576
459
|
end
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
return h
|
|
460
|
+
|
|
461
|
+
def clear
|
|
462
|
+
valkey.del(key)
|
|
581
463
|
end
|
|
582
464
|
end
|
|
583
465
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
466
|
+
# Sorted Set wrapper
|
|
467
|
+
class SortedSet
|
|
468
|
+
include Enumerable
|
|
469
|
+
attr_reader :key, :valkey
|
|
470
|
+
|
|
471
|
+
def initialize(key, valkey)
|
|
472
|
+
@key = key
|
|
473
|
+
@valkey = valkey
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def add(member, score)
|
|
477
|
+
valkey.zadd(key, score, member)
|
|
478
|
+
end
|
|
479
|
+
alias_method :[]=, :add
|
|
480
|
+
|
|
481
|
+
def score(member)
|
|
482
|
+
if !member?(member)
|
|
483
|
+
add(member, 0)
|
|
600
484
|
end
|
|
601
|
-
return
|
|
485
|
+
return valkey.zscore(key, member).to_f
|
|
602
486
|
end
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
487
|
+
alias_method :[], :score
|
|
488
|
+
|
|
489
|
+
def remove(member)
|
|
490
|
+
valkey.zrem(key, member)
|
|
606
491
|
end
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
VK.redis.call("ZINCRBY", key, 1, k)
|
|
492
|
+
|
|
493
|
+
def member?(member)
|
|
494
|
+
!valkey.zscore(key, member).nil?
|
|
611
495
|
end
|
|
612
|
-
|
|
496
|
+
alias_method :include?, :member?
|
|
613
497
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
a << b.call(i, JSON.parse(VK.redis.call("GET", e)))
|
|
620
|
-
else
|
|
621
|
-
a << JSON.parse(VK.redis.call("GET", e))
|
|
622
|
-
end
|
|
623
|
-
if @opts.has_key?(:flush) == true
|
|
624
|
-
VK.redis.call("DEL", e)
|
|
625
|
-
end
|
|
626
|
-
}
|
|
627
|
-
if @opts.has_key?(:flush) == true
|
|
628
|
-
delete!
|
|
498
|
+
def range(start_idx, end_idx, with_scores: true)
|
|
499
|
+
if with_scores
|
|
500
|
+
valkey.zrange(key, start_idx, end_idx, with_scores: true)
|
|
501
|
+
else
|
|
502
|
+
valkey.zrange(key, start_idx, end_idx)
|
|
629
503
|
end
|
|
630
|
-
return a
|
|
631
504
|
end
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
505
|
+
|
|
506
|
+
def revrange(start_idx, end_idx, with_scores: true)
|
|
507
|
+
if with_scores
|
|
508
|
+
valkey.zrevrange(key, start_idx, end_idx, with_scores: true)
|
|
509
|
+
else
|
|
510
|
+
valkey.zrevrange(key, start_idx, end_idx)
|
|
511
|
+
end
|
|
638
512
|
end
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
VK.redis.call("RPUSH", key, hx)
|
|
643
|
-
return hx
|
|
513
|
+
|
|
514
|
+
def members
|
|
515
|
+
range(0, -1)
|
|
644
516
|
end
|
|
645
|
-
|
|
646
|
-
|
|
517
|
+
|
|
518
|
+
def incr k, n
|
|
519
|
+
add(k, score(k) + n)
|
|
647
520
|
end
|
|
648
|
-
|
|
649
|
-
|
|
521
|
+
|
|
522
|
+
def decr k, n
|
|
523
|
+
add(k, score(k) - n)
|
|
650
524
|
end
|
|
651
|
-
end
|
|
652
525
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
end
|
|
657
|
-
def _index
|
|
658
|
-
%[#{key}-hash]
|
|
659
|
-
end
|
|
660
|
-
def length
|
|
661
|
-
VK.redis.call("SCARD", _set)
|
|
662
|
-
end
|
|
663
|
-
def value &b
|
|
664
|
-
VK.redis.call("HGETALL", _index).each_pair { |e, i| b.call(i, e) }
|
|
665
|
-
end
|
|
666
|
-
def [] i
|
|
667
|
-
if VK.redis.call("SMISMEMBER", _set, i)[0] == 0
|
|
668
|
-
VK.redis.call("SADD", _set, i)
|
|
669
|
-
VK.redis.call("HSET", _index, i, length);
|
|
670
|
-
end
|
|
671
|
-
return VK.redis.call("HGET", _index, i)
|
|
672
|
-
end
|
|
673
|
-
end
|
|
526
|
+
def up n, *a
|
|
527
|
+
[a].flatten.compact.each { |e| incr(e, n) }
|
|
528
|
+
end
|
|
674
529
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
%[#{key}-sset]
|
|
530
|
+
def dn n, *a
|
|
531
|
+
[a].flatten.compact.each { |e| decr(e, n) }
|
|
678
532
|
end
|
|
679
|
-
|
|
680
|
-
|
|
533
|
+
|
|
534
|
+
### KNN ###
|
|
535
|
+
def knn
|
|
536
|
+
KNN.new(members.map { |e| e[0] })
|
|
681
537
|
end
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
end
|
|
688
|
-
def length
|
|
689
|
-
VK.redis.call("SCARD", _set)
|
|
690
|
-
end
|
|
691
|
-
def value &b
|
|
692
|
-
VK.redis.call("HGETALL", _index).each_pair { |e, i| b.call(i.to_i, e) }
|
|
693
|
-
end
|
|
694
|
-
def entry
|
|
695
|
-
Hash.new { |h,k| VK.redis.call("HGET", _sec, k) }
|
|
696
|
-
end
|
|
697
|
-
def vectors
|
|
698
|
-
a = []
|
|
699
|
-
value { |i, e| a << [ i, VK.embed(e) ].flatten }
|
|
700
|
-
return a
|
|
701
|
-
end
|
|
702
|
-
def embed
|
|
703
|
-
return KNN.new(vectors, :distance_measure => :tanimoto_coefficient)
|
|
704
|
-
end
|
|
705
|
-
def near g, *n
|
|
706
|
-
return embed.nearest_neighbours(VK.embed(g)).map { |e|
|
|
707
|
-
{ index: e[0], distance: e[1], entry: entry[e[0]] }
|
|
708
|
-
}.sort_by { |ee| ee[:distance] }
|
|
709
|
-
end
|
|
710
|
-
def [] i
|
|
711
|
-
if VK.redis.call("SMISMEMBER", _set, i.to_s)[0] == 0
|
|
712
|
-
VK.redis.call("HSET", _index, i.to_s, length.to_s);
|
|
713
|
-
VK.redis.call("HSET", _sec, length.to_s, i.to_s);
|
|
714
|
-
VK.redis.call("SADD", _set, i)
|
|
715
|
-
end
|
|
716
|
-
return VK.redis.call("HGET", _index, i.to_s).to_i;
|
|
717
|
-
end
|
|
718
|
-
end
|
|
538
|
+
|
|
539
|
+
def size
|
|
540
|
+
valkey.zcard(key)
|
|
541
|
+
end
|
|
542
|
+
alias_method :length, :size
|
|
719
543
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
def self.classify a, b
|
|
728
|
-
ClassifierReborn::Bayes.new a, b
|
|
729
|
-
end
|
|
730
|
-
|
|
731
|
-
def self.threshold= n
|
|
732
|
-
@@SENTIMENT_THRESHOLD = n
|
|
733
|
-
end
|
|
734
|
-
##
|
|
735
|
-
# Sentiment Analysis.
|
|
736
|
-
##
|
|
737
|
-
# VK.feels("Some text")
|
|
738
|
-
def self.feels x
|
|
739
|
-
Sentimental.new(threshold: @@SENTIMENT_THRESHOLD).sentiment
|
|
740
|
-
end
|
|
741
|
-
|
|
742
|
-
@@CRi = Hash.new { |h,k| h[k] = CRi.new(k) }
|
|
743
|
-
class CRi
|
|
744
|
-
def initialize k
|
|
745
|
-
@id = k
|
|
746
|
-
@lsi = ClassifierReborn::LSI.new
|
|
747
|
-
end
|
|
748
|
-
def learn x, i
|
|
749
|
-
@lsi.add_item x.to_s, i.to_sym
|
|
750
|
-
end
|
|
751
|
-
def [] k
|
|
752
|
-
@lsi.classify k
|
|
753
|
-
end
|
|
754
|
-
def search x, *n
|
|
755
|
-
@lsi.search(x, n[0])
|
|
756
|
-
end
|
|
757
|
-
end
|
|
758
|
-
##
|
|
759
|
-
# Vector Indexing
|
|
760
|
-
#
|
|
761
|
-
# Vector (of text) -> concept (index)
|
|
762
|
-
# - Find text concept based upon known examples.
|
|
763
|
-
# - Learn new examples of a concept.
|
|
764
|
-
# - Find examples from within clusters.
|
|
765
|
-
##
|
|
766
|
-
# index[:vector]['Text to classify'] => :index
|
|
767
|
-
# index[:vector].learn("Text to classify", :index)
|
|
768
|
-
# index[:vector].search("Similar text.", 5) => ["Similar text?", "other similar text", ...]
|
|
769
|
-
def self.index
|
|
770
|
-
@@CRi
|
|
771
|
-
end
|
|
772
|
-
@@VI = Hash.new { |h,k| h[k] = [] }
|
|
773
|
-
@@VC = Hash.new { |h,k| h[k] = Knn::Classifier.new(@@VI[k], SquaredEuclideanCalculator) }
|
|
774
|
-
def self.learn fact, index
|
|
775
|
-
@@CRi[index.to_sym].learn fact, index
|
|
776
|
-
@@VI[index] << fact
|
|
777
|
-
end
|
|
778
|
-
|
|
779
|
-
@@TOKENIZER = Tokenizer::WhitespaceTokenizer.new(:en)
|
|
780
|
-
def self.tokenize i
|
|
781
|
-
@@TOKENIZER.tokenize(i)
|
|
782
|
-
end
|
|
544
|
+
def each(&block)
|
|
545
|
+
members.each(&block)
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
def expire(seconds)
|
|
549
|
+
valkey.expire(key, seconds)
|
|
550
|
+
end
|
|
783
551
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
end
|
|
552
|
+
def expireat(unix_timestamp)
|
|
553
|
+
valkey.expireat(key, unix_timestamp)
|
|
554
|
+
end
|
|
788
555
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
end
|
|
793
|
-
|
|
794
|
-
def self.flushdb!
|
|
795
|
-
VK.redis.call("FLUSHDB")
|
|
796
|
-
end
|
|
556
|
+
def ttl
|
|
557
|
+
valkey.ttl(key)
|
|
558
|
+
end
|
|
797
559
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
560
|
+
def persist
|
|
561
|
+
valkey.persist(key)
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def clear
|
|
565
|
+
valkey.del(key)
|
|
566
|
+
end
|
|
801
567
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
x.map { |e| b.call(e) }
|
|
806
|
-
else
|
|
807
|
-
return x
|
|
808
|
-
end
|
|
568
|
+
def delete
|
|
569
|
+
clear
|
|
570
|
+
end
|
|
809
571
|
end
|
|
810
572
|
end
|