Skip to content

Commit 430d75a

Browse files
committed
Fix TDIGEST.QUANTILE TDIGEST.MERGE TDIGEST.CDF
1 parent 76389f4 commit 430d75a

File tree

4 files changed

+55
-34
lines changed

4 files changed

+55
-34
lines changed

commons/src/main/java/io/github/dengliming/redismodule/common/util/RAssert.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020 dengliming.
2+
* Copyright 2020-2022 dengliming.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -67,6 +67,12 @@ public static void notEmpty(int[] array, String message) {
6767
}
6868
}
6969

70+
public static void notEmpty(double[] array, String message) {
71+
if (array == null || array.length == 0) {
72+
throw new IllegalArgumentException(message);
73+
}
74+
}
75+
7076
public static void isTrue(boolean value, String message) {
7177
if (!value) {
7278
throw new IllegalArgumentException(message);

redisbloom/src/main/java/io/github/dengliming/redismodule/redisbloom/TDigest.java

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 dengliming.
2+
* Copyright 2021-2022 dengliming.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -141,32 +141,45 @@ public RFuture<Double> getMaxAsync() {
141141
/**
142142
* Returns an estimate of the cutoff such that a specified fraction of the data added to this TDigest would be less than or equal to the cutoff.
143143
* <p>
144-
* TDIGEST.QUANTILE {key} {quantile}
144+
* TDIGEST.QUANTILE {key} quantile [quantile ...]
145145
*
146146
* @return
147147
*/
148-
public Double getQuantile(double quantile) {
149-
return get(getQuantileAsync(quantile));
148+
public List<Double> getQuantile(double... quantiles) {
149+
return get(getQuantileAsync(quantiles));
150150
}
151151

152-
public RFuture<Double> getQuantileAsync(double quantile) {
153-
return commandExecutor.readAsync(getName(), StringCodec.INSTANCE, TDIGEST_QUANTILE, getName(), quantile);
152+
public RFuture<List<Double>> getQuantileAsync(double... quantiles) {
153+
RAssert.notEmpty(quantiles, "quantiles must not be empty");
154+
155+
List<Object> params = new ArrayList<>(quantiles.length + 1);
156+
params.add(getName());
157+
for (double quantile : quantiles) {
158+
params.add(quantile);
159+
}
160+
return commandExecutor.readAsync(getName(), StringCodec.INSTANCE, TDIGEST_QUANTILE, params.toArray());
154161
}
155162

156163
/**
157164
* Returns the fraction of all points added which are <= value.
158165
* <p>
159-
* TDIGEST.CDF {key} {value}
166+
* TDIGEST.CDF {key} value [value ...]
160167
*
161-
* @param value
168+
* @param values
162169
* @return
163170
*/
164-
public Double getCdf(double value) {
165-
return get(getCdfAsync(value));
171+
public List<Double> getCdf(double... values) {
172+
return get(getCdfAsync(values));
166173
}
167174

168-
public RFuture<Double> getCdfAsync(double value) {
169-
return commandExecutor.readAsync(getName(), StringCodec.INSTANCE, TDIGEST_CDF, getName(), value);
175+
public RFuture<List<Double>> getCdfAsync(double... values) {
176+
RAssert.notEmpty(values, "values must not be empty");
177+
List<Object> params = new ArrayList<>(values.length + 1);
178+
params.add(getName());
179+
for (double value : values) {
180+
params.add(value);
181+
}
182+
return commandExecutor.readAsync(getName(), StringCodec.INSTANCE, TDIGEST_CDF, params.toArray());
170183
}
171184

172185
/**
@@ -180,7 +193,7 @@ public boolean mergeTo(String toKey) {
180193
}
181194

182195
public RFuture<Boolean> mergeToAsync(String toKey) {
183-
return commandExecutor.readAsync(getName(), StringCodec.INSTANCE, TDIGEST_MERGE, toKey, getName());
196+
return commandExecutor.readAsync(getName(), StringCodec.INSTANCE, TDIGEST_MERGE, toKey, 1, getName());
184197
}
185198

186199
/**

redisbloom/src/main/java/io/github/dengliming/redismodule/redisbloom/protocol/RedisCommands.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020 dengliming.
2+
* Copyright 2020-2022 dengliming.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -84,7 +84,7 @@ public interface RedisCommands {
8484
RedisCommand TDIGEST_INFO = new RedisCommand("TDIGEST.INFO", new ListMultiDecoder2(new TDigestDecoder()));
8585
RedisCommand TDIGEST_MIN = new RedisCommand("TDIGEST.MIN", new DoubleReplayConvertor());
8686
RedisCommand TDIGEST_MAX = new RedisCommand("TDIGEST.MAX", new DoubleReplayConvertor());
87-
RedisCommand TDIGEST_QUANTILE = new RedisCommand("TDIGEST.QUANTILE", new DoubleReplayConvertor());
88-
RedisCommand TDIGEST_CDF = new RedisCommand("TDIGEST.CDF", new DoubleReplayConvertor());
87+
RedisCommand<List<Double>> TDIGEST_QUANTILE = new RedisCommand("TDIGEST.QUANTILE", new ObjectListReplayDecoder(), new DoubleReplayConvertor());
88+
RedisCommand<List<Double>> TDIGEST_CDF = new RedisCommand("TDIGEST.CDF", new ObjectListReplayDecoder(), new DoubleReplayConvertor());
8989
RedisCommand TDIGEST_MERGE = new RedisCommand("TDIGEST.MERGE", new BooleanReplayConvertor());
9090
}

redisbloom/src/test/java/io/github/dengliming/redismodule/redisbloom/TDigestTest.java

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 dengliming.
2+
* Copyright 2021-2022 dengliming.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,10 +17,11 @@
1717
package io.github.dengliming.redismodule.redisbloom;
1818

1919
import io.github.dengliming.redismodule.redisbloom.model.TDigestInfo;
20-
import org.assertj.core.data.Offset;
2120
import org.junit.jupiter.api.Test;
21+
2222
import java.util.AbstractMap;
2323
import java.util.ArrayList;
24+
import java.util.Arrays;
2425
import java.util.List;
2526

2627
import static org.assertj.core.api.Assertions.assertThat;
@@ -72,32 +73,33 @@ public void testMinAndMax() {
7273
public void testQuantile() {
7374
TDigest tDigest = getRedisBloomClient().getTDigest("t-digest");
7475
assertThat(tDigest.create(500)).isTrue();
75-
76-
List<AbstractMap.SimpleEntry<Double, Double>> vals = new ArrayList<>();
77-
for (int i = 1; i <= 10000; i++) {
78-
vals.add(new AbstractMap.SimpleEntry(i * 0.01, 1.0));
79-
}
76+
List<AbstractMap.SimpleEntry<Double, Double>> vals = Arrays.asList(
77+
new AbstractMap.SimpleEntry(1.0, 1.0),
78+
new AbstractMap.SimpleEntry(2.0, 1.0),
79+
new AbstractMap.SimpleEntry(3.0, 1.0)
80+
);
8081

8182
assertThat(tDigest.add(vals)).isTrue();
8283

83-
assertThat(tDigest.getQuantile(0.01)).isCloseTo(1.0, Offset.offset(0.01));
84-
assertThat(tDigest.getQuantile(0.99)).isCloseTo(99.0, Offset.offset(0.01));
84+
assertThat(tDigest.getQuantile(1.0).get(0)).isEqualTo(3.0);
85+
assertThat(tDigest.getQuantile(0).get(0)).isEqualTo(1.0);
8586
}
8687

8788
@Test
8889
public void testCdf() {
8990
TDigest tDigest = getRedisBloomClient().getTDigest("t-digest");
9091
assertThat(tDigest.create(500)).isTrue();
9192

92-
List<AbstractMap.SimpleEntry<Double, Double>> vals = new ArrayList<>();
93-
for (int i = 1; i <= 100; i++) {
94-
vals.add(new AbstractMap.SimpleEntry(i, 1.0));
95-
}
93+
List<AbstractMap.SimpleEntry<Double, Double>> vals = Arrays.asList(
94+
new AbstractMap.SimpleEntry(1.0, 1.0),
95+
new AbstractMap.SimpleEntry(2.0, 1.0),
96+
new AbstractMap.SimpleEntry(3.0, 1.0)
97+
);
9698

9799
assertThat(tDigest.add(vals)).isTrue();
98100

99-
assertThat(tDigest.getCdf(1.0)).isCloseTo(0.01, Offset.offset(0.01));
100-
assertThat(tDigest.getCdf(99.0)).isCloseTo(0.99, Offset.offset(0.01));
101+
assertThat(tDigest.getCdf(10.0).get(0)).isEqualTo(1.0);
102+
assertThat(tDigest.getCdf(0.0).get(0)).isEqualTo(0.0);
101103
}
102104

103105
@Test
@@ -114,7 +116,7 @@ public void testReset() {
114116

115117
TDigestInfo tDigestInfo = tDigest.getInfo();
116118
assertThat(tDigestInfo).isNotNull();
117-
assertThat(tDigestInfo.getUnmergedNodes()).isEqualTo(100);
119+
assertThat(tDigestInfo.getUnmergedNodes()).isEqualTo(200);
118120

119121
assertThat(tDigest.reset()).isTrue();
120122
tDigestInfo = tDigest.getInfo();
@@ -145,6 +147,6 @@ public void testMerge() {
145147

146148
TDigestInfo toDigestInfo = toDigest.getInfo();
147149
assertThat(toDigestInfo).isNotNull();
148-
assertThat(toDigestInfo.getMergedWeight() + toDigestInfo.getUnmergedWeight()).isEqualTo(1100);
150+
assertThat(toDigestInfo.getMergedWeight() + toDigestInfo.getUnmergedWeight()).isEqualTo(400);
149151
}
150152
}

0 commit comments

Comments
 (0)