valkey-objects 0.4.8 → 0.5.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.
- 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 +486 -723
- data/lib/valkey/objects.rb~ +10 -0
- metadata +15 -153
- data/valkey-objects.gemspec +0 -49
data/lib/valkey/objects.rb
CHANGED
|
@@ -1,813 +1,576 @@
|
|
|
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)
|
|
304
164
|
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
165
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
VK.redis.call("SET", key, "#{VK.clock.to_i}");
|
|
166
|
+
def expire(seconds)
|
|
167
|
+
valkey.expire(key, seconds)
|
|
317
168
|
end
|
|
318
|
-
|
|
319
|
-
|
|
169
|
+
|
|
170
|
+
def expireat(unix_timestamp)
|
|
171
|
+
valkey.expireat(key, unix_timestamp)
|
|
320
172
|
end
|
|
321
|
-
|
|
322
|
-
|
|
173
|
+
|
|
174
|
+
def ttl
|
|
175
|
+
valkey.ttl(key)
|
|
323
176
|
end
|
|
324
|
-
|
|
325
|
-
|
|
177
|
+
|
|
178
|
+
def persist
|
|
179
|
+
valkey.persist(key)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def to_s
|
|
183
|
+
value.to_s
|
|
326
184
|
end
|
|
327
185
|
end
|
|
328
186
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
187
|
+
# Counter wrapper
|
|
188
|
+
class Counter
|
|
189
|
+
attr_reader :key, :valkey
|
|
190
|
+
|
|
191
|
+
def initialize(key, valkey)
|
|
192
|
+
@key = key
|
|
193
|
+
@valkey = valkey
|
|
336
194
|
end
|
|
337
|
-
|
|
338
|
-
VK.redis.call("GET", key) ? true : false
|
|
339
|
-
end
|
|
195
|
+
|
|
340
196
|
def value= x
|
|
341
|
-
|
|
197
|
+
valkey.set(key, x)
|
|
342
198
|
end
|
|
343
|
-
|
|
344
|
-
if self.value == true || self.value == nil
|
|
345
|
-
self.value = false
|
|
346
|
-
else
|
|
347
|
-
self.value = true
|
|
348
|
-
end
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
class VALUE < O
|
|
199
|
+
|
|
353
200
|
def value
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
delete!
|
|
357
|
-
end
|
|
358
|
-
return x
|
|
201
|
+
val = valkey.get(key)
|
|
202
|
+
val ? val.to_i : 0
|
|
359
203
|
end
|
|
360
|
-
|
|
361
|
-
|
|
204
|
+
|
|
205
|
+
def increment(by = 1)
|
|
206
|
+
valkey.incrby(key, by)
|
|
362
207
|
end
|
|
363
|
-
|
|
364
|
-
|
|
208
|
+
|
|
209
|
+
def decrement(by = 1)
|
|
210
|
+
valkey.decrby(key, by)
|
|
365
211
|
end
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
212
|
+
|
|
213
|
+
def reset
|
|
214
|
+
valkey.set(key, 0)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def delete
|
|
218
|
+
valkey.del(key)
|
|
373
219
|
end
|
|
374
|
-
end
|
|
375
220
|
|
|
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)
|
|
221
|
+
def expire(seconds)
|
|
222
|
+
valkey.expire(key, seconds)
|
|
430
223
|
end
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
end
|
|
439
|
-
return x
|
|
224
|
+
|
|
225
|
+
def expireat(unix_timestamp)
|
|
226
|
+
valkey.expireat(key, unix_timestamp)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def ttl
|
|
230
|
+
valkey.ttl(key)
|
|
440
231
|
end
|
|
441
|
-
|
|
442
|
-
|
|
232
|
+
|
|
233
|
+
def persist
|
|
234
|
+
valkey.persist(key)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def to_i
|
|
238
|
+
value.to_i
|
|
443
239
|
end
|
|
444
|
-
def exist?
|
|
445
|
-
VK.redis.call("GET", @key) ? true : false
|
|
446
|
-
end
|
|
447
240
|
end
|
|
448
241
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
242
|
+
# List wrapper
|
|
243
|
+
class List
|
|
244
|
+
include Enumerable
|
|
245
|
+
attr_reader :key, :valkey
|
|
246
|
+
|
|
247
|
+
def initialize(key, valkey)
|
|
248
|
+
@key = key
|
|
249
|
+
@valkey = valkey
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def <<(value)
|
|
253
|
+
valkey.rpush(key, value)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def push(*values)
|
|
257
|
+
valkey.rpush(key, values)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def unshift(*values)
|
|
261
|
+
valkey.lpush(key, values.reverse)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def pop
|
|
265
|
+
valkey.rpop(key)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def shift
|
|
269
|
+
valkey.lpop(key)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def [](index)
|
|
273
|
+
valkey.lindex(key, index)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def []=(index, value)
|
|
277
|
+
valkey.lset(key, index, value)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def length
|
|
281
|
+
valkey.llen(key)
|
|
452
282
|
end
|
|
453
|
-
|
|
454
|
-
|
|
283
|
+
alias_method :size, :length
|
|
284
|
+
|
|
285
|
+
def range(start_idx, end_idx)
|
|
286
|
+
valkey.lrange(key, start_idx, end_idx)
|
|
455
287
|
end
|
|
456
|
-
|
|
457
|
-
|
|
288
|
+
|
|
289
|
+
def values
|
|
290
|
+
range(0, -1)
|
|
458
291
|
end
|
|
459
|
-
|
|
460
|
-
|
|
292
|
+
|
|
293
|
+
def each(&block)
|
|
294
|
+
values.each(&block)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def expire(seconds)
|
|
298
|
+
valkey.expire(key, seconds)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def expireat(unix_timestamp)
|
|
302
|
+
valkey.expireat(key, unix_timestamp)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def ttl
|
|
306
|
+
valkey.ttl(key)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def persist
|
|
310
|
+
valkey.persist(key)
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
### KNN ###
|
|
314
|
+
def knn
|
|
315
|
+
KNN.new(values)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def clear
|
|
320
|
+
valkey.del(key)
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def delete
|
|
324
|
+
clear
|
|
461
325
|
end
|
|
462
326
|
end
|
|
463
327
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
328
|
+
# Set wrapper
|
|
329
|
+
class Set
|
|
330
|
+
include Enumerable
|
|
331
|
+
attr_reader :key, :valkey
|
|
332
|
+
|
|
333
|
+
def initialize(key, valkey)
|
|
334
|
+
@key = key
|
|
335
|
+
@valkey = valkey
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def add(value)
|
|
339
|
+
valkey.sadd(key, value)
|
|
340
|
+
end
|
|
341
|
+
alias_method :<<, :add
|
|
342
|
+
|
|
343
|
+
def remove(value)
|
|
344
|
+
valkey.srem(key, value)
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def member?(value)
|
|
348
|
+
valkey.sismember(key, value)
|
|
349
|
+
end
|
|
350
|
+
alias_method :include?, :member?
|
|
351
|
+
|
|
352
|
+
def members
|
|
353
|
+
valkey.smembers(key)
|
|
354
|
+
end
|
|
355
|
+
alias_method :to_a, :members
|
|
356
|
+
|
|
357
|
+
def size
|
|
358
|
+
valkey.scard(key)
|
|
359
|
+
end
|
|
360
|
+
alias_method :length, :size
|
|
361
|
+
|
|
362
|
+
def each(&block)
|
|
363
|
+
members.each(&block)
|
|
470
364
|
end
|
|
471
|
-
|
|
472
|
-
|
|
365
|
+
|
|
366
|
+
def expire(seconds)
|
|
367
|
+
valkey.expire(key, seconds)
|
|
473
368
|
end
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
def << i
|
|
478
|
-
VK.redis.call("RPUSH", key, i)
|
|
369
|
+
|
|
370
|
+
def expireat(unix_timestamp)
|
|
371
|
+
valkey.expireat(key, unix_timestamp)
|
|
479
372
|
end
|
|
480
|
-
|
|
481
|
-
|
|
373
|
+
|
|
374
|
+
def ttl
|
|
375
|
+
valkey.ttl(key)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def persist
|
|
379
|
+
valkey.persist(key)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
### KNN ###
|
|
383
|
+
def knn
|
|
384
|
+
KNN.new(members)
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def clear
|
|
388
|
+
valkey.del(key)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def delete
|
|
392
|
+
clear
|
|
482
393
|
end
|
|
483
394
|
end
|
|
484
395
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
396
|
+
# Hash wrapper
|
|
397
|
+
class HashKey
|
|
398
|
+
include Enumerable
|
|
399
|
+
attr_reader :key, :valkey
|
|
400
|
+
|
|
401
|
+
def initialize(key, valkey)
|
|
402
|
+
@key = key
|
|
403
|
+
@valkey = valkey
|
|
491
404
|
end
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return h
|
|
405
|
+
|
|
406
|
+
def [](field)
|
|
407
|
+
valkey.hget(key, field)
|
|
496
408
|
end
|
|
497
|
-
|
|
498
|
-
|
|
409
|
+
|
|
410
|
+
def []=(field, value)
|
|
411
|
+
valkey.hset(key, field, value)
|
|
499
412
|
end
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
def poke k, n
|
|
504
|
-
VK.redis.call("ZINCRBY", key, n.to_f, k);
|
|
413
|
+
|
|
414
|
+
def fetch(field, default = nil)
|
|
415
|
+
valkey.hget(key, field) || default
|
|
505
416
|
end
|
|
506
|
-
end
|
|
507
417
|
|
|
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
|
|
418
|
+
def delete(field)
|
|
419
|
+
valkey.hdel(key, field)
|
|
522
420
|
end
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
else
|
|
527
|
-
return true
|
|
528
|
-
end
|
|
421
|
+
|
|
422
|
+
def key?(field)
|
|
423
|
+
valkey.hexists(key, field)
|
|
529
424
|
end
|
|
530
|
-
|
|
531
|
-
|
|
425
|
+
alias_method :has_key?, :key?
|
|
426
|
+
|
|
427
|
+
def keys
|
|
428
|
+
valkey.hkeys(key)
|
|
532
429
|
end
|
|
533
|
-
|
|
534
|
-
|
|
430
|
+
|
|
431
|
+
def values
|
|
432
|
+
valkey.hvals(key)
|
|
535
433
|
end
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
def & k
|
|
540
|
-
VK.redis.call("SINTER", key, k.key)
|
|
434
|
+
|
|
435
|
+
def all
|
|
436
|
+
valkey.hgetall(key)
|
|
541
437
|
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
|
|
438
|
+
alias_method :to_h, :all
|
|
439
|
+
|
|
440
|
+
def size
|
|
441
|
+
valkey.hlen(key)
|
|
549
442
|
end
|
|
550
|
-
|
|
551
|
-
|
|
443
|
+
alias_method :length, :size
|
|
444
|
+
|
|
445
|
+
def expire(seconds)
|
|
446
|
+
valkey.expire(key, seconds)
|
|
552
447
|
end
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
def value &b
|
|
557
|
-
a = []
|
|
558
|
-
VK.redis.call("ZRANGE", key, 0, -1).each_with_index { |e, i|
|
|
559
|
-
if block_given?
|
|
560
|
-
a << b.call(i, e)
|
|
561
|
-
else
|
|
562
|
-
a << e
|
|
563
|
-
end
|
|
564
|
-
};
|
|
565
|
-
if @opts.has_key?(:flush) == true
|
|
566
|
-
delete!
|
|
567
|
-
end
|
|
568
|
-
return a
|
|
448
|
+
|
|
449
|
+
def expireat(unix_timestamp)
|
|
450
|
+
valkey.expireat(key, unix_timestamp)
|
|
569
451
|
end
|
|
570
|
-
|
|
571
|
-
|
|
452
|
+
|
|
453
|
+
def ttl
|
|
454
|
+
valkey.ttl(key)
|
|
572
455
|
end
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
456
|
+
|
|
457
|
+
def persist
|
|
458
|
+
valkey.persist(key)
|
|
576
459
|
end
|
|
577
|
-
|
|
578
|
-
|
|
460
|
+
|
|
461
|
+
def each(&block)
|
|
462
|
+
all.each(&block)
|
|
579
463
|
end
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
return h
|
|
464
|
+
|
|
465
|
+
def clear
|
|
466
|
+
valkey.del(key)
|
|
584
467
|
end
|
|
585
468
|
end
|
|
586
469
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
470
|
+
# Sorted Set wrapper
|
|
471
|
+
class SortedSet
|
|
472
|
+
include Enumerable
|
|
473
|
+
attr_reader :key, :valkey
|
|
474
|
+
|
|
475
|
+
def initialize(key, valkey)
|
|
476
|
+
@key = key
|
|
477
|
+
@valkey = valkey
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def add(member, score)
|
|
481
|
+
valkey.zadd(key, score, member)
|
|
482
|
+
end
|
|
483
|
+
alias_method :[]=, :add
|
|
484
|
+
|
|
485
|
+
def score(member)
|
|
486
|
+
if !member?(member)
|
|
487
|
+
add(member, 0)
|
|
603
488
|
end
|
|
604
|
-
return
|
|
489
|
+
return valkey.zscore(key, member).to_f
|
|
605
490
|
end
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
491
|
+
alias_method :[], :score
|
|
492
|
+
|
|
493
|
+
def remove(member)
|
|
494
|
+
valkey.zrem(key, member)
|
|
609
495
|
end
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
VK.redis.call("ZINCRBY", key, 1, k)
|
|
496
|
+
|
|
497
|
+
def member?(member)
|
|
498
|
+
!valkey.zscore(key, member).nil?
|
|
614
499
|
end
|
|
615
|
-
|
|
500
|
+
alias_method :include?, :member?
|
|
616
501
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
a << b.call(i, JSON.parse(VK.redis.call("GET", e)))
|
|
623
|
-
else
|
|
624
|
-
a << JSON.parse(VK.redis.call("GET", e))
|
|
625
|
-
end
|
|
626
|
-
if @opts.has_key?(:flush) == true
|
|
627
|
-
VK.redis.call("DEL", e)
|
|
628
|
-
end
|
|
629
|
-
}
|
|
630
|
-
if @opts.has_key?(:flush) == true
|
|
631
|
-
delete!
|
|
502
|
+
def range(start_idx, end_idx, with_scores: true)
|
|
503
|
+
if with_scores
|
|
504
|
+
valkey.zrange(key, start_idx, end_idx, with_scores: true)
|
|
505
|
+
else
|
|
506
|
+
valkey.zrange(key, start_idx, end_idx)
|
|
632
507
|
end
|
|
633
|
-
return a
|
|
634
|
-
end
|
|
635
|
-
def length
|
|
636
|
-
VK.redis.call("LLEN", key)
|
|
637
508
|
end
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
509
|
+
|
|
510
|
+
def revrange(start_idx, end_idx, with_scores: true)
|
|
511
|
+
if with_scores
|
|
512
|
+
valkey.zrevrange(key, start_idx, end_idx, with_scores: true)
|
|
513
|
+
else
|
|
514
|
+
valkey.zrevrange(key, start_idx, end_idx)
|
|
515
|
+
end
|
|
641
516
|
end
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
VK.redis.call("RPUSH", key, hx)
|
|
646
|
-
return hx
|
|
517
|
+
|
|
518
|
+
def members
|
|
519
|
+
range(0, -1)
|
|
647
520
|
end
|
|
648
|
-
|
|
649
|
-
|
|
521
|
+
|
|
522
|
+
def incr k, n
|
|
523
|
+
add(k, score(k) + n)
|
|
650
524
|
end
|
|
651
|
-
|
|
652
|
-
|
|
525
|
+
|
|
526
|
+
def decr k, n
|
|
527
|
+
add(k, score(k) - n)
|
|
653
528
|
end
|
|
654
|
-
end
|
|
655
529
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
end
|
|
660
|
-
def _index
|
|
661
|
-
%[#{key}-hash]
|
|
662
|
-
end
|
|
663
|
-
def length
|
|
664
|
-
VK.redis.call("SCARD", _set)
|
|
665
|
-
end
|
|
666
|
-
def value &b
|
|
667
|
-
VK.redis.call("HGETALL", _index).each_pair { |e, i| b.call(i, e) }
|
|
668
|
-
end
|
|
669
|
-
def [] i
|
|
670
|
-
if VK.redis.call("SMISMEMBER", _set, i)[0] == 0
|
|
671
|
-
VK.redis.call("SADD", _set, i)
|
|
672
|
-
VK.redis.call("HSET", _index, i, length);
|
|
673
|
-
end
|
|
674
|
-
return VK.redis.call("HGET", _index, i)
|
|
675
|
-
end
|
|
676
|
-
end
|
|
530
|
+
def up n, *a
|
|
531
|
+
[a].flatten.compact.each { |e| incr(e, n) }
|
|
532
|
+
end
|
|
677
533
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
%[#{key}-sset]
|
|
534
|
+
def dn n, *a
|
|
535
|
+
[a].flatten.compact.each { |e| decr(e, n) }
|
|
681
536
|
end
|
|
682
|
-
|
|
683
|
-
|
|
537
|
+
|
|
538
|
+
### KNN ###
|
|
539
|
+
def knn
|
|
540
|
+
KNN.new(members.map { |e| e[0] })
|
|
684
541
|
end
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
end
|
|
691
|
-
def length
|
|
692
|
-
VK.redis.call("SCARD", _set)
|
|
693
|
-
end
|
|
694
|
-
def value &b
|
|
695
|
-
VK.redis.call("HGETALL", _index).each_pair { |e, i| b.call(i.to_i, e) }
|
|
696
|
-
end
|
|
697
|
-
def entry
|
|
698
|
-
Hash.new { |h,k| VK.redis.call("HGET", _sec, k) }
|
|
699
|
-
end
|
|
700
|
-
def vectors
|
|
701
|
-
a = []
|
|
702
|
-
value { |i, e| a << [ i, VK.embed(e) ].flatten }
|
|
703
|
-
return a
|
|
704
|
-
end
|
|
705
|
-
def embed
|
|
706
|
-
return KNN.new(vectors, :distance_measure => :tanimoto_coefficient)
|
|
707
|
-
end
|
|
708
|
-
def near g, *n
|
|
709
|
-
return embed.nearest_neighbours(VK.embed(g)).map { |e|
|
|
710
|
-
{ index: e[0], distance: e[1], entry: entry[e[0]] }
|
|
711
|
-
}.sort_by { |ee| ee[:distance] }
|
|
712
|
-
end
|
|
713
|
-
def [] i
|
|
714
|
-
if VK.redis.call("SMISMEMBER", _set, i.to_s)[0] == 0
|
|
715
|
-
VK.redis.call("HSET", _index, i.to_s, length.to_s);
|
|
716
|
-
VK.redis.call("HSET", _sec, length.to_s, i.to_s);
|
|
717
|
-
VK.redis.call("SADD", _set, i)
|
|
718
|
-
end
|
|
719
|
-
return VK.redis.call("HGET", _index, i.to_s).to_i;
|
|
720
|
-
end
|
|
721
|
-
end
|
|
542
|
+
|
|
543
|
+
def size
|
|
544
|
+
valkey.zcard(key)
|
|
545
|
+
end
|
|
546
|
+
alias_method :length, :size
|
|
722
547
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
def self.classify a, b
|
|
731
|
-
ClassifierReborn::Bayes.new a, b
|
|
732
|
-
end
|
|
733
|
-
|
|
734
|
-
def self.threshold= n
|
|
735
|
-
@@SENTIMENT_THRESHOLD = n
|
|
736
|
-
end
|
|
737
|
-
##
|
|
738
|
-
# Sentiment Analysis.
|
|
739
|
-
##
|
|
740
|
-
# VK.feels("Some text")
|
|
741
|
-
def self.feels x
|
|
742
|
-
Sentimental.new(threshold: @@SENTIMENT_THRESHOLD).sentiment
|
|
743
|
-
end
|
|
744
|
-
|
|
745
|
-
@@CRi = Hash.new { |h,k| h[k] = CRi.new(k) }
|
|
746
|
-
class CRi
|
|
747
|
-
def initialize k
|
|
748
|
-
@id = k
|
|
749
|
-
@lsi = ClassifierReborn::LSI.new
|
|
750
|
-
end
|
|
751
|
-
def learn x, i
|
|
752
|
-
@lsi.add_item x.to_s, i.to_sym
|
|
753
|
-
end
|
|
754
|
-
def [] k
|
|
755
|
-
@lsi.classify k
|
|
756
|
-
end
|
|
757
|
-
def search x, *n
|
|
758
|
-
@lsi.search(x, n[0])
|
|
759
|
-
end
|
|
760
|
-
end
|
|
761
|
-
##
|
|
762
|
-
# Vector Indexing
|
|
763
|
-
#
|
|
764
|
-
# Vector (of text) -> concept (index)
|
|
765
|
-
# - Find text concept based upon known examples.
|
|
766
|
-
# - Learn new examples of a concept.
|
|
767
|
-
# - Find examples from within clusters.
|
|
768
|
-
##
|
|
769
|
-
# index[:vector]['Text to classify'] => :index
|
|
770
|
-
# index[:vector].learn("Text to classify", :index)
|
|
771
|
-
# index[:vector].search("Similar text.", 5) => ["Similar text?", "other similar text", ...]
|
|
772
|
-
def self.index
|
|
773
|
-
@@CRi
|
|
774
|
-
end
|
|
775
|
-
@@VI = Hash.new { |h,k| h[k] = [] }
|
|
776
|
-
@@VC = Hash.new { |h,k| h[k] = Knn::Classifier.new(@@VI[k], SquaredEuclideanCalculator) }
|
|
777
|
-
def self.learn fact, index
|
|
778
|
-
@@CRi[index.to_sym].learn fact, index
|
|
779
|
-
@@VI[index] << fact
|
|
780
|
-
end
|
|
781
|
-
|
|
782
|
-
@@TOKENIZER = Tokenizer::WhitespaceTokenizer.new(:en)
|
|
783
|
-
def self.tokenize i
|
|
784
|
-
@@TOKENIZER.tokenize(i)
|
|
785
|
-
end
|
|
548
|
+
def each(&block)
|
|
549
|
+
members.each(&block)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def expire(seconds)
|
|
553
|
+
valkey.expire(key, seconds)
|
|
554
|
+
end
|
|
786
555
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
end
|
|
556
|
+
def expireat(unix_timestamp)
|
|
557
|
+
valkey.expireat(key, unix_timestamp)
|
|
558
|
+
end
|
|
791
559
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
end
|
|
796
|
-
|
|
797
|
-
def self.flushdb!
|
|
798
|
-
VK.redis.call("FLUSHDB")
|
|
799
|
-
end
|
|
560
|
+
def ttl
|
|
561
|
+
valkey.ttl(key)
|
|
562
|
+
end
|
|
800
563
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
564
|
+
def persist
|
|
565
|
+
valkey.persist(key)
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def clear
|
|
569
|
+
valkey.del(key)
|
|
570
|
+
end
|
|
804
571
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
x.map { |e| b.call(e) }
|
|
809
|
-
else
|
|
810
|
-
return x
|
|
811
|
-
end
|
|
572
|
+
def delete
|
|
573
|
+
clear
|
|
574
|
+
end
|
|
812
575
|
end
|
|
813
576
|
end
|