redtastic 0.2.1 → 0.2.2
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 +8 -8
- data/.gitignore +10 -0
- data/.rubocop.yml +17 -0
- data/.travis.yml +17 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +84 -0
- data/README.md +275 -0
- data/lib/redtastic/connection.rb +14 -0
- data/lib/redtastic/model.rb +285 -0
- data/lib/redtastic/script_manager.rb +32 -0
- data/lib/redtastic/scripts/data_points_for_keys.lua +37 -0
- data/lib/redtastic/scripts/hmfind.lua +14 -0
- data/lib/redtastic/scripts/hmincrby.lua +9 -0
- data/lib/redtastic/scripts/msadd.lua +3 -0
- data/lib/redtastic/scripts/msismember.lua +7 -0
- data/lib/redtastic/scripts/msrem.lua +3 -0
- data/lib/redtastic/scripts/msunion.lua +28 -0
- data/lib/redtastic/scripts/sum.lua +13 -0
- data/lib/redtastic/scripts/union_data_points_for_keys.lua +51 -0
- data/lib/redtastic/version.rb +3 -0
- data/redtastic.gemspec +27 -0
- data/spec/connection_spec.rb +42 -0
- data/spec/model_spec.rb +776 -0
- data/spec/sample_scripts/sample.lua +1 -0
- data/spec/sample_scripts/sample_with_args.lua +1 -0
- data/spec/script_manager_spec.rb +24 -0
- data/spec/spec_helper.rb +26 -0
- metadata +34 -2
data/spec/model_spec.rb
ADDED
@@ -0,0 +1,776 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Redtastic::Model do
|
4
|
+
|
5
|
+
it 'validates type' do
|
6
|
+
expect do
|
7
|
+
class InvalidType < Redtastic::Model
|
8
|
+
type :foo
|
9
|
+
end
|
10
|
+
end.to raise_error(RuntimeError, 'foo is not a valid type')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'validates resolution' do
|
14
|
+
expect do
|
15
|
+
class InvalidResolution < Redtastic::Model
|
16
|
+
type :counter
|
17
|
+
resolution :foo
|
18
|
+
end
|
19
|
+
end.to raise_error(RuntimeError, 'foo is not a valid resolution')
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'counter' do
|
23
|
+
before do
|
24
|
+
class Visits < Redtastic::Model
|
25
|
+
type :counter
|
26
|
+
resolution :days
|
27
|
+
end
|
28
|
+
|
29
|
+
class NoResolutions < Redtastic::Model
|
30
|
+
type :counter
|
31
|
+
end
|
32
|
+
|
33
|
+
@no_resolution_key = 'app1:no_resolutions:1'
|
34
|
+
@day_key = 'app1:visits:2014-01-05:1'
|
35
|
+
@week_key = 'app1:visits:2014-W1:1'
|
36
|
+
@month_key = 'app1:visits:2014-01:1'
|
37
|
+
@year_key = 'app1:visits:2014:1'
|
38
|
+
@id = 1001
|
39
|
+
@index = 1
|
40
|
+
@timestamp = '2014-01-05'
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#increment' do
|
44
|
+
context 'a model with a daily resolution' do
|
45
|
+
before do
|
46
|
+
Visits.increment(timestamp: @timestamp, id: @id)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'increments the daily key' do
|
50
|
+
expect(Redtastic::Connection.redis.hget(@day_key, @index)).to eq('1')
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'increments the weekly key' do
|
54
|
+
expect(Redtastic::Connection.redis.hget(@week_key, @index)).to eq('1')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'increments the monthly key' do
|
58
|
+
expect(Redtastic::Connection.redis.hget(@month_key, @index)).to eq('1')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'increments the yearly key' do
|
62
|
+
expect(Redtastic::Connection.redis.hget(@year_key, @index)).to eq('1')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'a model with no resolution' do
|
67
|
+
it 'increments the key' do
|
68
|
+
NoResolutions.increment(id: @id)
|
69
|
+
expect(Redtastic::Connection.redis.hget(@no_resolution_key, @index)).to eq('1')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'multiple ids' do
|
74
|
+
before do
|
75
|
+
ids = [1001, 1002, 2003]
|
76
|
+
Visits.increment(timestamp: @timestamp, id: ids)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'increments the keys for each id' do
|
80
|
+
expect(Redtastic::Connection.redis.hget(@day_key, '1')).to eq('1')
|
81
|
+
expect(Redtastic::Connection.redis.hget(@day_key, '2')).to eq('1')
|
82
|
+
expect(Redtastic::Connection.redis.hget('app1:visits:2014-01-05:2', '3')).to eq('1')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#decrement' do
|
88
|
+
before do
|
89
|
+
Redtastic::Connection.redis.hset(@day_key, @index, '1')
|
90
|
+
Visits.decrement(timestamp: @timestamp, id: @id)
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'a model with a resolution' do
|
94
|
+
it 'decrements the key' do
|
95
|
+
expect(Redtastic::Connection.redis.hget(@day_key, @index)).to eq('0')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'a model with no resolution' do
|
100
|
+
before do
|
101
|
+
Redtastic::Connection.redis.hset(@no_resolution_key, @index, '1')
|
102
|
+
NoResolutions.decrement(id: @id)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'decrements the key' do
|
106
|
+
expect(Redtastic::Connection.redis.hget(@no_resolution_key, @index)).to eq('0')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'multiple ids' do
|
111
|
+
before do
|
112
|
+
ids = [1001, 1002, 2003]
|
113
|
+
Visits.decrement(timestamp: @timestamp, id: ids)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'decrements the keys for each id' do
|
117
|
+
expect(Redtastic::Connection.redis.hget(@day_key, '1')).to eq('-1')
|
118
|
+
expect(Redtastic::Connection.redis.hget(@day_key, '2')).to eq('-1')
|
119
|
+
expect(Redtastic::Connection.redis.hget('app1:visits:2014-01-05:2', '3')).to eq('-1')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#find' do
|
125
|
+
context 'a model with a resolution' do
|
126
|
+
before do
|
127
|
+
Visits.increment(timestamp: @timestamp, id: @id)
|
128
|
+
Visits.increment(timestamp: '2014-01-02', id: @id)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'finds the value for a single day' do
|
132
|
+
expect(Visits.find(year: 2014, month: 1, day: 5, id: @id)).to eq(1)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'finds the value for a single week' do
|
136
|
+
expect(Visits.find(year: 2014, week: 1, id: @id)).to eq(2)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'finds the value for a single month' do
|
140
|
+
expect(Visits.find(year: 2014, month: 1, id: @id)).to eq(2)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'finds the value for a single year' do
|
144
|
+
expect(Visits.find(year: 2014, id: @id)).to eq(2)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'a model with no resolution' do
|
149
|
+
before do
|
150
|
+
3.times { NoResolutions.increment(id: @id) }
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'finds the value for the counter' do
|
154
|
+
expect(NoResolutions.find(id: @id)).to eq(3)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'mutiple ids' do
|
159
|
+
before do
|
160
|
+
2.times { Visits.increment(timestamp: @timestamp, id: 1001) }
|
161
|
+
Visits.increment(timestamp: @timestamp, id: 2003)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'returns an array of the values for each id' do
|
165
|
+
expected_result = [2, 1]
|
166
|
+
expect(Visits.find(year: 2014, month: 1, day: 5, id: [1001, 2003])).to eq(expected_result)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe '#aggregate' do
|
172
|
+
context 'when no interval specified' do
|
173
|
+
it 'returns the total over the date range' do
|
174
|
+
9.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:1", '1', 1) }
|
175
|
+
res = Visits.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
176
|
+
expect(res).to eq(9)
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'returns the correct total over the date range when resolution is weeks' do
|
180
|
+
class Foo < Redtastic::Model
|
181
|
+
type :counter
|
182
|
+
resolution :weeks
|
183
|
+
end
|
184
|
+
3.times { |num| Redtastic::Connection.redis.hincrby("app1:foo:2014-W#{num}:1", '1', 1) }
|
185
|
+
res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
186
|
+
expect(res).to eq(2)
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'returns the correct total over the date range when the resolution is months' do
|
190
|
+
class Foo < Redtastic::Model
|
191
|
+
type :counter
|
192
|
+
resolution :months
|
193
|
+
end
|
194
|
+
3.times { Redtastic::Connection.redis.hincrby('app1:foo:2014-01:1', '1', 1) }
|
195
|
+
res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
196
|
+
expect(res).to eq(3)
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'returns the correct total over the date range when resolution is yearly' do
|
200
|
+
class Foo < Redtastic::Model
|
201
|
+
type :counter
|
202
|
+
resolution :years
|
203
|
+
end
|
204
|
+
3.times { Redtastic::Connection.redis.hincrby('app1:foo:2014:1', '1', 1) }
|
205
|
+
res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
206
|
+
expect(res).to eq(3)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when interval is specified' do
|
211
|
+
before do
|
212
|
+
@params = { start_date: '2014-01-01', end_date: '2014-01-08', id: @id }
|
213
|
+
8.times { |day| Visits.increment(timestamp: "2014-01-0#{day + 1}", id: @id) }
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'and is days' do
|
217
|
+
before do
|
218
|
+
@params[:interval] = :days
|
219
|
+
@result = Visits.aggregate(@params)
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'returns the total over the date range' do
|
223
|
+
expect(@result[:visits]).to eq(8)
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'returns the proper amount of data points' do
|
227
|
+
expect(@result[:days].size).to eq(8)
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'returns the correct data for each point in the interval' do
|
231
|
+
@result[:days].each do |day|
|
232
|
+
expect(day[:visits]).to eq(1)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'returns the correct dates for each point in the interval' do
|
237
|
+
current_date = Date.parse(@params[:start_date])
|
238
|
+
@result[:days].each do |day|
|
239
|
+
expect(day[:date]).to eq(current_date.strftime('%Y-%m-%d'))
|
240
|
+
current_date = current_date.advance(days: +1)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'and is weeks' do
|
246
|
+
before do
|
247
|
+
@params[:interval] = :weeks
|
248
|
+
@result = Visits.aggregate(@params)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'returns the total over the date range' do
|
252
|
+
expect(@result[:visits]).to eq(8)
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'returns the proper amount of data points' do
|
256
|
+
expect(@result[:weeks].size).to eq(2)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'returns the correct data for each point in the interval' do
|
260
|
+
expect(@result[:weeks][0][:visits]).to eq(5)
|
261
|
+
expect(@result[:weeks][1][:visits]).to eq(3)
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'returns the correct dates for each point in the interval' do
|
265
|
+
expect(@result[:weeks][0][:date]).to eq('2014-W1')
|
266
|
+
expect(@result[:weeks][1][:date]).to eq('2014-W2')
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'and is months' do
|
271
|
+
before do
|
272
|
+
@params[:interval] = :months
|
273
|
+
@result = Visits.aggregate(@params)
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'returns the total over the date range' do
|
277
|
+
expect(@result[:visits]).to eq(8)
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'returns the proper amount of data points' do
|
281
|
+
expect(@result[:months].size).to eq(1)
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'returns the correct data for each point in the interval' do
|
285
|
+
expect(@result[:months][0][:visits]).to eq(8)
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'returns the correct dates for each point in the interval' do
|
289
|
+
expect(@result[:months][0][:date]).to eq('2014-01')
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context 'and is years' do
|
294
|
+
before do
|
295
|
+
@params[:interval] = :years
|
296
|
+
@result = Visits.aggregate(@params)
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'returns the total over the date range' do
|
300
|
+
expect(@result[:visits]).to eq(8)
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'returns the proper amount of data points' do
|
304
|
+
expect(@result[:years].size).to eq(1)
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'returns the correct data for each point in the interval' do
|
308
|
+
expect(@result[:years][0][:visits]).to eq(8)
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'returns the correct dates for each point in the interval' do
|
312
|
+
expect(@result[:years][0][:date]).to eq('2014')
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'mutiple ids' do
|
318
|
+
before do
|
319
|
+
9.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:1", '1', 1) }
|
320
|
+
3.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:2", '3', 1) }
|
321
|
+
@params = { start_date: '2014-01-01', end_date: '2014-01-09', id: [1001, 2003] }
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'when no interval is specified' do
|
325
|
+
it 'returns the aggregate total for both ids combined' do
|
326
|
+
result = Visits.aggregate(@params)
|
327
|
+
expect(result).to eq(12)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context 'when an interval is specified' do
|
332
|
+
before do
|
333
|
+
@result = Visits.aggregate(@params.merge!(interval: :days))
|
334
|
+
end
|
335
|
+
|
336
|
+
it 'returns the total over the date range' do
|
337
|
+
expect(@result[:visits]).to eq(12)
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'returns the proper amount of data points' do
|
341
|
+
expect(@result[:days].size).to eq(9)
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'returns the correct data for each point in the interval' do
|
345
|
+
3.times do |num|
|
346
|
+
expect(@result[:days][num][:visits]).to eq(2)
|
347
|
+
end
|
348
|
+
(3..8).each do |num|
|
349
|
+
expect(@result[:days][num][:visits]).to eq(1)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
context 'unique counter' do
|
358
|
+
before do
|
359
|
+
class Customers < Redtastic::Model
|
360
|
+
type :unique
|
361
|
+
resolution :days
|
362
|
+
end
|
363
|
+
@id = 1001
|
364
|
+
@timestamp = '2014-01-05'
|
365
|
+
@user1 = 4321
|
366
|
+
@user2 = 8765
|
367
|
+
@day_key = 'app1:customers:2014-01-05:1001'
|
368
|
+
@week_key = 'app1:customers:2014-W1:1001'
|
369
|
+
@month_key = 'app1:customers:2014-01:1001'
|
370
|
+
@year_key = 'app1:customers:2014:1001'
|
371
|
+
end
|
372
|
+
|
373
|
+
describe '#increment' do
|
374
|
+
context 'single ids' do
|
375
|
+
before do
|
376
|
+
Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user1)
|
377
|
+
Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user2)
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'adds user 1 to the set' do
|
381
|
+
expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
|
382
|
+
end
|
383
|
+
|
384
|
+
it 'adds user 2 to the set' do
|
385
|
+
expect(Redtastic::Connection.redis.sismember(@day_key, @user2)).to be true
|
386
|
+
end
|
387
|
+
|
388
|
+
it 'adds user 1 to the weekly set' do
|
389
|
+
expect(Redtastic::Connection.redis.sismember(@week_key, @user1)).to be true
|
390
|
+
end
|
391
|
+
|
392
|
+
it 'adds user 1 to the monthly set' do
|
393
|
+
expect(Redtastic::Connection.redis.sismember(@month_key, @user1)).to be true
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'adds user 1 to the yearly set' do
|
397
|
+
expect(Redtastic::Connection.redis.sismember(@year_key, @user1)).to be true
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
context 'multiple ids' do
|
402
|
+
before do
|
403
|
+
ids = [1001, 1002]
|
404
|
+
Customers.increment(id: ids, timestamp: @timestamp, unique_id: @user1)
|
405
|
+
end
|
406
|
+
|
407
|
+
it 'increments bits on both keys' do
|
408
|
+
expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
|
409
|
+
expect(Redtastic::Connection.redis.sismember('app1:customers:2014-01-05:1002', @user1)).to be true
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
describe '#decrement' do
|
415
|
+
before do
|
416
|
+
# First add user 1
|
417
|
+
Redtastic::Connection.redis.sadd(@day_key, @user1)
|
418
|
+
end
|
419
|
+
|
420
|
+
it 'decrements user1 removing it from the set' do
|
421
|
+
# Make sure it was properly added first
|
422
|
+
expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
|
423
|
+
Customers.decrement(id: @id, timestamp: @timestamp, unique_id: @user1)
|
424
|
+
expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be false
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
describe '#find' do
|
429
|
+
context 'single ids' do
|
430
|
+
before do
|
431
|
+
Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user1)
|
432
|
+
end
|
433
|
+
|
434
|
+
it 'finds the value for a unique id on a single day' do
|
435
|
+
expect(Customers.find(id: @id, year: 2014, month: 1, day: 5, unique_id: @user1)).to eq(1)
|
436
|
+
expect(Customers.find(id: @id, year: 2014, month: 1, day: 5, unique_id: 1)).to eq(0)
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'finds the value for a unique id in a single week' do
|
440
|
+
expect(Customers.find(id: @id, year: 2014, week: 1, unique_id: @user1)).to eq(1)
|
441
|
+
expect(Customers.find(id: @id, year: 2014, week: 1, unique_id: 1)).to eq(0)
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'finds the value for a unique id in a single month' do
|
445
|
+
expect(Customers.find(id: @id, year: 2014, month: 1, unique_id: @user1)).to eq(1)
|
446
|
+
expect(Customers.find(id: @id, year: 2014, month: 1, unique_id: 1)).to eq(0)
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'finds the value for a unique id in a single year' do
|
450
|
+
expect(Customers.find(id: @id, year: 2014, unique_id: @user1)).to eq(1)
|
451
|
+
expect(Customers.find(id: @id, year: 2014, unique_id: 1)).to eq(0)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
context 'mutiple ids' do
|
456
|
+
before do
|
457
|
+
2.times { Customers.increment(id: 1001, timestamp: @timestamp, unique_id: @user1) }
|
458
|
+
Customers.increment(id: 1002, timestamp: @timestamp, unique_id: @user1)
|
459
|
+
end
|
460
|
+
|
461
|
+
it 'returns an array of the values for each id' do
|
462
|
+
expected_result = [1, 1, 0]
|
463
|
+
params = { id: [1001, 1002, 1003], year: 2014, month: 1, day: 5, unique_id: @user1 }
|
464
|
+
expect(Customers.find(params)).to eq(expected_result)
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
describe '#aggregate' do
|
470
|
+
context 'when no interval is specified' do
|
471
|
+
it 'returns the total over the date range' do
|
472
|
+
9.times { |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{@id}", @user1) }
|
473
|
+
3.times { |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{@id}", @user2) }
|
474
|
+
result = Customers.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
475
|
+
expect(result).to eq(2)
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'returns the correct total over the date range when the resolution is weeks' do
|
479
|
+
class Foo < Redtastic::Model
|
480
|
+
type :unique
|
481
|
+
resolution :weeks
|
482
|
+
end
|
483
|
+
3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-W#{num}:#{@id}", @user1) }
|
484
|
+
2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-W#{num}:#{@id}", @user2) }
|
485
|
+
result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
486
|
+
expect(result).to eq(2)
|
487
|
+
end
|
488
|
+
|
489
|
+
it 'returns the correct total over the date range when the resolution is months' do
|
490
|
+
class Foo < Redtastic::Model
|
491
|
+
type :unique
|
492
|
+
resolution :months
|
493
|
+
end
|
494
|
+
3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-01:#{@id}", @user1) }
|
495
|
+
2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-01:#{@id}", @user2) }
|
496
|
+
result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
497
|
+
expect(result).to eq(2)
|
498
|
+
end
|
499
|
+
|
500
|
+
it 'returns the correct total over the date range when the resolution is years' do
|
501
|
+
class Foo < Redtastic::Model
|
502
|
+
type :unique
|
503
|
+
resolution :years
|
504
|
+
end
|
505
|
+
3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014:#{@id}", @user1) }
|
506
|
+
2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014:#{@id}", @user2) }
|
507
|
+
result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
|
508
|
+
expect(result).to eq(2)
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
context 'when interval is specified' do
|
513
|
+
before do
|
514
|
+
@params = { start_date: '2014-01-01', end_date: '2014-01-09', id: @id }
|
515
|
+
9.times { |day| Customers.increment(id: @id, timestamp: "2014-01-0#{day + 1}", unique_id: @user1) }
|
516
|
+
3.times { |day| Customers.increment(id: @id, timestamp: "2014-01-0#{day + 1}", unique_id: @user2) }
|
517
|
+
end
|
518
|
+
|
519
|
+
context 'and is days' do
|
520
|
+
before do
|
521
|
+
@params[:interval] = :days
|
522
|
+
@result = Customers.aggregate(@params)
|
523
|
+
end
|
524
|
+
|
525
|
+
it 'returns the total over the date range' do
|
526
|
+
expect(@result[:customers]).to eq(2)
|
527
|
+
end
|
528
|
+
|
529
|
+
it 'returns the proper amount of data points' do
|
530
|
+
expect(@result[:days].size).to eq(9)
|
531
|
+
end
|
532
|
+
|
533
|
+
it 'returns the correct data for each point in the interval' do
|
534
|
+
3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
|
535
|
+
6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(1) }
|
536
|
+
end
|
537
|
+
|
538
|
+
it 'returns the correct dates for each point in the interval' do
|
539
|
+
current_date = Date.parse(@params[:start_date])
|
540
|
+
@result[:days].each do |day|
|
541
|
+
expect(day[:date]).to eq(current_date.strftime('%Y-%m-%d'))
|
542
|
+
current_date = current_date.advance(days: +1)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
context 'and is weeks' do
|
548
|
+
before do
|
549
|
+
@params[:interval] = :weeks
|
550
|
+
@result = Customers.aggregate(@params)
|
551
|
+
end
|
552
|
+
|
553
|
+
it 'returns the total over the date range' do
|
554
|
+
expect(@result[:customers]).to eq(2)
|
555
|
+
end
|
556
|
+
|
557
|
+
it 'returns the proper amount of data points' do
|
558
|
+
expect(@result[:weeks].size).to eq(2)
|
559
|
+
end
|
560
|
+
|
561
|
+
it 'returns the correct data for each point in the interval' do
|
562
|
+
expect(@result[:weeks][0][:customers]).to eq(2)
|
563
|
+
expect(@result[:weeks][1][:customers]).to eq(1)
|
564
|
+
end
|
565
|
+
|
566
|
+
it 'returns the correct dates for each point in the interval' do
|
567
|
+
expect(@result[:weeks][0][:date]).to eq('2014-W1')
|
568
|
+
expect(@result[:weeks][1][:date]).to eq('2014-W2')
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
context 'and is years' do
|
573
|
+
before do
|
574
|
+
@params[:interval] = :years
|
575
|
+
@result = Customers.aggregate(@params)
|
576
|
+
end
|
577
|
+
|
578
|
+
it 'returns the total over the date range' do
|
579
|
+
expect(@result[:customers]).to eq(2)
|
580
|
+
end
|
581
|
+
|
582
|
+
it 'returns the proper amount of data points' do
|
583
|
+
expect(@result[:years].size).to eq(1)
|
584
|
+
end
|
585
|
+
|
586
|
+
it 'returns the correct data for each point in the interval' do
|
587
|
+
expect(@result[:years][0][:customers]).to eq(2)
|
588
|
+
end
|
589
|
+
|
590
|
+
it 'returns the correct dates for each point in the interval' do
|
591
|
+
expect(@result[:years][0][:date]).to eq('2014')
|
592
|
+
end
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
context 'multiple ids' do
|
597
|
+
before do
|
598
|
+
9.times do |day|
|
599
|
+
Customers.increment(id: 1001, timestamp: "2014-01-0#{day + 1}", unique_id: @user1)
|
600
|
+
Customers.increment(id: 1002, timestamp: "2014-01-0#{day + 1}", unique_id: @user1)
|
601
|
+
end
|
602
|
+
3.times { |day| Customers.increment(id: 1001, timestamp: "2014-01-0#{day + 1}", unique_id: @user2) }
|
603
|
+
@params = { start_date: '2014-01-01', end_date: '2014-01-09', id: [1001, 2003] }
|
604
|
+
end
|
605
|
+
|
606
|
+
context 'when no interval is specified' do
|
607
|
+
it 'returns the aggregate total for both ids combined' do
|
608
|
+
result = Customers.aggregate(@params)
|
609
|
+
expect(result).to eq(2)
|
610
|
+
end
|
611
|
+
end
|
612
|
+
|
613
|
+
context 'when an interval is specified' do
|
614
|
+
before do
|
615
|
+
@result = Customers.aggregate(@params.merge!(interval: :days))
|
616
|
+
end
|
617
|
+
|
618
|
+
it 'returns the total over the date range' do
|
619
|
+
expect(@result[:customers]).to eq(2)
|
620
|
+
end
|
621
|
+
|
622
|
+
it 'returns the proper amount of data points' do
|
623
|
+
expect(@result[:days].size).to eq(9)
|
624
|
+
end
|
625
|
+
|
626
|
+
it 'returns the correct data for each point in the interval' do
|
627
|
+
3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
|
628
|
+
(3..8).each { |num| expect(@result[:days][num][:customers]).to eq(1) }
|
629
|
+
end
|
630
|
+
end
|
631
|
+
end
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
context 'attributes' do
|
636
|
+
before do
|
637
|
+
class Customers < Redtastic::Model
|
638
|
+
type :unique
|
639
|
+
resolution :days
|
640
|
+
end
|
641
|
+
class Males < Redtastic::Model
|
642
|
+
type :unique
|
643
|
+
end
|
644
|
+
class Mobile < Redtastic::Model
|
645
|
+
type :unique
|
646
|
+
end
|
647
|
+
@user1 = 1111
|
648
|
+
@user2 = 2222
|
649
|
+
@user3 = 3333
|
650
|
+
@attribute_key = 'app1:males'
|
651
|
+
end
|
652
|
+
|
653
|
+
describe '#increment' do
|
654
|
+
before do
|
655
|
+
Males.increment(unique_id: @user1)
|
656
|
+
Males.increment(unique_id: @user2)
|
657
|
+
end
|
658
|
+
|
659
|
+
it 'adds user1 to the set' do
|
660
|
+
result = Redtastic::Connection.redis.sismember(@attribute_key, @user1)
|
661
|
+
expect(result).to be true
|
662
|
+
end
|
663
|
+
|
664
|
+
it 'adds user2 to the set' do
|
665
|
+
result = Redtastic::Connection.redis.sismember(@attribute_key, @user2)
|
666
|
+
expect(result).to be true
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
describe '#decrement' do
|
671
|
+
before do
|
672
|
+
Males.increment(unique_id: @user1)
|
673
|
+
end
|
674
|
+
|
675
|
+
it 'adds user1 to the set' do
|
676
|
+
Males.decrement(unique_id: @user1)
|
677
|
+
result = Redtastic::Connection.redis.sismember(@attribute_key, @user1)
|
678
|
+
expect(result).to be false
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
describe '#find' do
|
683
|
+
before do
|
684
|
+
Males.increment(unique_id: @user1)
|
685
|
+
end
|
686
|
+
|
687
|
+
it 'returns 1 for a unique_id that is in the attribute set' do
|
688
|
+
expect(Males.find(unique_id: @user1)).to eq(1)
|
689
|
+
end
|
690
|
+
|
691
|
+
it 'returns 0 for a unique_id that is not in the attribute set' do
|
692
|
+
expect(Males.find(unique_id: @user2)).to eq(0)
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
describe '#aggregate' do
|
697
|
+
before do
|
698
|
+
Males.increment(unique_id: @user1)
|
699
|
+
Males.increment(unique_id: @user2)
|
700
|
+
Mobile.increment(unique_id: @user2)
|
701
|
+
9.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{2222}", @user1) }
|
702
|
+
3.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{1111}", @user2) }
|
703
|
+
3.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{1111}", @user3) }
|
704
|
+
@params = { id: [1111, 2222], start_date: '2014-01-01', end_date: '2014-01-09' }
|
705
|
+
@attributes = []
|
706
|
+
end
|
707
|
+
|
708
|
+
context 'when no interval is specified' do
|
709
|
+
context 'and single attribute is specified' do
|
710
|
+
it 'returns the total over the date range' do
|
711
|
+
@attributes << :males
|
712
|
+
result = Customers.aggregate(@params.merge!(attributes: @attributes))
|
713
|
+
expect(result).to eq(2)
|
714
|
+
end
|
715
|
+
|
716
|
+
it 'does not require use of an array if specifying only one attribute' do
|
717
|
+
result = Customers.aggregate(@params.merge!(attributes: :males))
|
718
|
+
expect(result).to eq(2)
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
context 'and multiple attributes are specified' do
|
723
|
+
it 'returns the total over the date range' do
|
724
|
+
@attributes << :males
|
725
|
+
@attributes << :mobile
|
726
|
+
result = Customers.aggregate(@params.merge!(attributes: @attributes))
|
727
|
+
expect(result).to eq(1)
|
728
|
+
end
|
729
|
+
end
|
730
|
+
end
|
731
|
+
|
732
|
+
context 'when interval is specified' do
|
733
|
+
context 'and single attribute is specified' do
|
734
|
+
before do
|
735
|
+
@attributes << :males
|
736
|
+
@result = Customers.aggregate(@params.merge!(attributes: @attributes, interval: :days))
|
737
|
+
end
|
738
|
+
|
739
|
+
it 'returns the total over the date range' do
|
740
|
+
expect(@result[:customers]).to eq(2)
|
741
|
+
end
|
742
|
+
|
743
|
+
it 'returns the proper amount of data points' do
|
744
|
+
expect(@result[:days].size).to eq(9)
|
745
|
+
end
|
746
|
+
|
747
|
+
it 'returns the correct data for each point in the interval' do
|
748
|
+
3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
|
749
|
+
6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(1) }
|
750
|
+
end
|
751
|
+
end
|
752
|
+
|
753
|
+
context 'and multiple attributes are specified' do
|
754
|
+
before do
|
755
|
+
@attributes << :males
|
756
|
+
@attributes << :mobile
|
757
|
+
@result = Customers.aggregate(@params.merge!(attributes: @attributes, interval: :days))
|
758
|
+
end
|
759
|
+
|
760
|
+
it 'returns the total over the date range' do
|
761
|
+
expect(@result[:customers]).to eq(1)
|
762
|
+
end
|
763
|
+
|
764
|
+
it 'returns the proper amount of data points' do
|
765
|
+
expect(@result[:days].size).to eq(9)
|
766
|
+
end
|
767
|
+
|
768
|
+
it 'returns the correct data for each point in the interval' do
|
769
|
+
3.times { |num| expect(@result[:days][num][:customers]).to eq(1) }
|
770
|
+
6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(0) }
|
771
|
+
end
|
772
|
+
end
|
773
|
+
end
|
774
|
+
end
|
775
|
+
end
|
776
|
+
end
|