Skip to content

Commit 4219f40

Browse files
committed
Add HyperLogLog commands (#431)
1 parent 813a424 commit 4219f40

File tree

5 files changed

+142
-0
lines changed

5 files changed

+142
-0
lines changed

lib/redis.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2415,6 +2415,39 @@ def sscan_each(key, options={}, &block)
24152415
end
24162416
end
24172417

2418+
# Add one or more members to a HyperLogLog structure.
2419+
#
2420+
# @param [String] key
2421+
# @param [String, Array<String>] member one member, or array of members
2422+
# @return [Boolean] true if at least 1 HyperLogLog internal register was altered. false otherwise.
2423+
def pfadd(key, member)
2424+
synchronize do |client|
2425+
client.call([:pfadd, key, member], &_boolify)
2426+
end
2427+
end
2428+
2429+
# Get the approximate cardinality of members added to HyperLogLog structure.
2430+
#
2431+
# @param [String] key
2432+
# @return [Fixnum]
2433+
def pfcount(key)
2434+
synchronize do |client|
2435+
client.call([:pfcount, key])
2436+
end
2437+
end
2438+
2439+
# Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
2440+
# the observed Sets of the source HyperLogLog structures.
2441+
#
2442+
# @param [String] dest_key destination key
2443+
# @param [String, Array<String>] source_key source key, or array of keys
2444+
# @return [Boolean]
2445+
def pfmerge(dest_key, *source_key)
2446+
synchronize do |client|
2447+
client.call([:pfmerge, dest_key, *source_key], &_boolify_set)
2448+
end
2449+
end
2450+
24182451
def id
24192452
@original_client.id
24202453
end

lib/redis/distributed.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,24 @@ def script(subcommand, *args)
781781
on_each_node(:script, subcommand, *args)
782782
end
783783

784+
# Add one or more members to a HyperLogLog structure.
785+
def pfadd(key, member)
786+
node_for(key).pfadd(key, member)
787+
end
788+
789+
# Get the approximate cardinality of members added to HyperLogLog structure.
790+
def pfcount(key)
791+
node_for(key).pfcount(key)
792+
end
793+
794+
# Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
795+
# the observed Sets of the source HyperLogLog structures.
796+
def pfmerge(dest_key, *source_key)
797+
ensure_same_node(:pfmerge, [dest_key, *source_key]) do |node|
798+
node.pfmerge(dest_key, *source_key)
799+
end
800+
end
801+
784802
def _eval(cmd, args)
785803
script = args.shift
786804
options = args.pop if args.last.is_a?(Hash)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# encoding: UTF-8
2+
3+
require File.expand_path("helper", File.dirname(__FILE__))
4+
require "lint/hyper_log_log"
5+
6+
class TestCommandsOnHyperLogLog < Test::Unit::TestCase
7+
8+
include Helper::Client
9+
include Lint::HyperLogLog
10+
11+
def test_pfmerge
12+
target_version "2.8.9" do
13+
r.pfadd "foo", "s1"
14+
r.pfadd "bar", "s2"
15+
16+
assert_equal true, r.pfmerge("res", "foo", "bar")
17+
assert_equal 2, r.pfcount("res")
18+
end
19+
end
20+
21+
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# encoding: UTF-8
2+
3+
require File.expand_path("helper", File.dirname(__FILE__))
4+
require "lint/hyper_log_log"
5+
6+
class TestDistributedCommandsOnHyperLogLog < Test::Unit::TestCase
7+
8+
include Helper::Distributed
9+
include Lint::HyperLogLog
10+
11+
def test_pfmerge
12+
target_version "2.8.9" do
13+
assert_raise Redis::Distributed::CannotDistribute do
14+
r.pfadd "foo", "s1"
15+
r.pfadd "bar", "s2"
16+
17+
assert r.pfmerge("res", "foo", "bar")
18+
end
19+
end
20+
end
21+
22+
end

test/lint/hyper_log_log.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module Lint
2+
3+
module HyperLogLog
4+
5+
def test_pfadd
6+
target_version "2.8.9" do
7+
assert_equal true, r.pfadd("foo", "s1")
8+
assert_equal true, r.pfadd("foo", "s2")
9+
assert_equal false, r.pfadd("foo", "s1")
10+
11+
assert_equal 2, r.pfcount("foo")
12+
end
13+
end
14+
15+
def test_variadic_pfadd
16+
target_version "2.8.9" do
17+
assert_equal true, r.pfadd("foo", ["s1", "s2"])
18+
assert_equal true, r.pfadd("foo", ["s1", "s2", "s3"])
19+
20+
assert_equal 3, r.pfcount("foo")
21+
end
22+
end
23+
24+
def test_pfcount
25+
target_version "2.8.9" do
26+
assert_equal 0, r.pfcount("foo")
27+
28+
assert_equal true, r.pfadd("foo", "s1")
29+
30+
assert_equal 1, r.pfcount("foo")
31+
end
32+
end
33+
34+
def test_variadic_pfcount
35+
target_version "2.8.9" do
36+
assert_equal 0, r.pfcount(["foo", "bar"])
37+
38+
assert_equal true, r.pfadd("foo", "s1")
39+
assert_equal true, r.pfadd("bar", "s1")
40+
assert_equal true, r.pfadd("bar", "s2")
41+
42+
assert_equal 2, r.pfcount(["foo", "bar"])
43+
end
44+
end
45+
46+
end
47+
48+
end

0 commit comments

Comments
 (0)