summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordvora-h <67596500+dvora-h@users.noreply.github.com>2022-09-21 11:53:16 +0300
committerGitHub <noreply@github.com>2022-09-21 11:53:16 +0300
commit027b452316534d7ba868f3d58cfebc8cf1a9a804 (patch)
tree1b53d495234a4c03c944e1c1a63a55ff41f63260
parent66c4e600646f37918943dcda4ae9f65cf14781f0 (diff)
downloadredis-py-027b452316534d7ba868f3d58cfebc8cf1a9a804.tar.gz
Add support for new TDIGEST features and changes (#2392)
* Add support to TDIGEST * linters * linters * linters * disable View Test Results in CI
-rw-r--r--.github/workflows/integration.yaml30
-rw-r--r--redis/commands/bf/__init__.py9
-rw-r--r--redis/commands/bf/commands.py62
-rw-r--r--redis/commands/bf/info.py24
-rw-r--r--redis/commands/bf/utils.py3
-rw-r--r--tests/test_asyncio/test_bloom.py99
-rw-r--r--tests/test_bloom.py90
7 files changed, 229 insertions, 88 deletions
diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml
index c1110b1..4812f8a 100644
--- a/.github/workflows/integration.yaml
+++ b/.github/workflows/integration.yaml
@@ -71,21 +71,21 @@ jobs:
with:
name: pytest-results-${{matrix.test-type}}
path: '${{matrix.test-type}}*results.xml'
- - name: View Test Results
- uses: dorny/test-reporter@v1
- if: success() || failure()
- with:
- name: Test Results ${{matrix.python-version}} ${{matrix.test-type}}-${{matrix.connection-type}}
- path: '${{matrix.test-type}}*results.xml'
- reporter: java-junit
- list-suites: failed
- list-tests: failed
- max-annotations: 10
- - name: Upload codecov coverage
- uses: codecov/codecov-action@v2
- with:
- fail_ci_if_error: false
- token: ${{ secrets.CODECOV_TOKEN }}
+ # - name: View Test Results
+ # uses: dorny/test-reporter@v1
+ # if: success() || failure()
+ # with:
+ # name: Test Results ${{matrix.python-version}} ${{matrix.test-type}}-${{matrix.connection-type}}
+ # path: '${{matrix.test-type}}*results.xml'
+ # reporter: java-junit
+ # list-suites: failed
+ # list-tests: failed
+ # max-annotations: 10
+ # - name: Upload codecov coverage
+ # uses: codecov/codecov-action@v2
+ # with:
+ # fail_ci_if_error: false
+ # token: ${{ secrets.CODECOV_TOKEN }}
build_and_test_package:
name: Validate building and installing the package
diff --git a/redis/commands/bf/__init__.py b/redis/commands/bf/__init__.py
index e41354b..a448def 100644
--- a/redis/commands/bf/__init__.py
+++ b/redis/commands/bf/__init__.py
@@ -3,7 +3,6 @@ from redis.client import bool_ok
from ..helpers import parse_to_list
from .commands import * # noqa
from .info import BFInfo, CFInfo, CMSInfo, TDigestInfo, TopKInfo
-from .utils import parse_tdigest_quantile
class AbstractBloom(object):
@@ -166,12 +165,16 @@ class TDigestBloom(TDigestCommands, AbstractBloom):
# TDIGEST_RESET: bool_ok,
# TDIGEST_ADD: spaceHolder,
# TDIGEST_MERGE: spaceHolder,
- TDIGEST_CDF: float,
- TDIGEST_QUANTILE: parse_tdigest_quantile,
+ TDIGEST_CDF: parse_to_list,
+ TDIGEST_QUANTILE: parse_to_list,
TDIGEST_MIN: float,
TDIGEST_MAX: float,
TDIGEST_TRIMMED_MEAN: float,
TDIGEST_INFO: TDigestInfo,
+ TDIGEST_RANK: parse_to_list,
+ TDIGEST_REVRANK: parse_to_list,
+ TDIGEST_BYRANK: parse_to_list,
+ TDIGEST_BYREVRANK: parse_to_list,
}
self.client = client
diff --git a/redis/commands/bf/commands.py b/redis/commands/bf/commands.py
index 3d085e6..71c9c8a 100644
--- a/redis/commands/bf/commands.py
+++ b/redis/commands/bf/commands.py
@@ -52,7 +52,10 @@ TDIGEST_MIN = "TDIGEST.MIN"
TDIGEST_MAX = "TDIGEST.MAX"
TDIGEST_INFO = "TDIGEST.INFO"
TDIGEST_TRIMMED_MEAN = "TDIGEST.TRIMMED_MEAN"
-TDIGEST_MERGESTORE = "TDIGEST.MERGESTORE"
+TDIGEST_RANK = "TDIGEST.RANK"
+TDIGEST_REVRANK = "TDIGEST.REVRANK"
+TDIGEST_BYRANK = "TDIGEST.BYRANK"
+TDIGEST_BYREVRANK = "TDIGEST.BYREVRANK"
class BFCommands:
@@ -381,12 +384,22 @@ class TDigestCommands:
self.append_values_and_weights(params, values, weights)
return self.execute_command(TDIGEST_ADD, *params)
- def merge(self, toKey, fromKey):
+ def merge(self, destination_key, num_keys, *keys, compression=None, override=False):
"""
- Merge all of the values from 'fromKey' to 'toKey' sketch.
+ Merges all of the values from `keys` to 'destination-key' sketch.
+ It is mandatory to provide the `num_keys` before passing the input keys and
+ the other (optional) arguments.
+ If `destination_key` already exists its values are merged with the input keys.
+ If you wish to override the destination key contents use the `OVERRIDE` parameter.
+
For more information see `TDIGEST.MERGE <https://redis.io/commands/tdigest.merge>`_.
""" # noqa
- return self.execute_command(TDIGEST_MERGE, toKey, fromKey)
+ params = [destination_key, num_keys, *keys]
+ if compression is not None:
+ params.extend(["COMPRESSION", compression])
+ if override:
+ params.append("OVERRIDE")
+ return self.execute_command(TDIGEST_MERGE, *params)
def min(self, key):
"""
@@ -411,12 +424,12 @@ class TDigestCommands:
""" # noqa
return self.execute_command(TDIGEST_QUANTILE, key, quantile, *quantiles)
- def cdf(self, key, value):
+ def cdf(self, key, value, *values):
"""
Return double fraction of all points added which are <= value.
For more information see `TDIGEST.CDF <https://redis.io/commands/tdigest.cdf>`_.
""" # noqa
- return self.execute_command(TDIGEST_CDF, key, value)
+ return self.execute_command(TDIGEST_CDF, key, value, *values)
def info(self, key):
"""
@@ -436,18 +449,39 @@ class TDigestCommands:
TDIGEST_TRIMMED_MEAN, key, low_cut_quantile, high_cut_quantile
)
- def mergestore(self, dest_key, numkeys, *sourcekeys, compression=False):
+ def rank(self, key, value, *values):
"""
- Merges all of the values from `sourcekeys` keys to `dest_key` sketch.
- If destination already exists, it is overwritten.
+ Retrieve the estimated rank of value (the number of observations in the sketch
+ that are smaller than value + half the number of observations that are equal to value).
+ For more information see `TDIGEST.RANK <https://redis.io/commands/tdigest.rank>`_.
+ """ # noqa
+ return self.execute_command(TDIGEST_RANK, key, value, *values)
- For more information see `TDIGEST.MERGESTORE <https://redis.io/commands/tdigest.mergestore>`_.
+ def revrank(self, key, value, *values):
+ """
+ Retrieve the estimated rank of value (the number of observations in the sketch
+ that are larger than value + half the number of observations that are equal to value).
+
+ For more information see `TDIGEST.REVRANK <https://redis.io/commands/tdigest.revrank>`_.
""" # noqa
- params = [dest_key, numkeys, *sourcekeys]
- if compression:
- params.extend(["COMPRESSION", compression])
- return self.execute_command(TDIGEST_MERGESTORE, *params)
+ return self.execute_command(TDIGEST_REVRANK, key, value, *values)
+
+ def byrank(self, key, rank, *ranks):
+ """
+ Retrieve an estimation of the value with the given rank.
+
+ For more information see `TDIGEST.BY_RANK <https://redis.io/commands/tdigest.by_rank>`_.
+ """ # noqa
+ return self.execute_command(TDIGEST_BYRANK, key, rank, *ranks)
+
+ def byrevrank(self, key, rank, *ranks):
+ """
+ Retrieve an estimation of the value with the given reverse rank.
+
+ For more information see `TDIGEST.BY_REVRANK <https://redis.io/commands/tdigest.by_revrank>`_.
+ """ # noqa
+ return self.execute_command(TDIGEST_BYREVRANK, key, rank, *ranks)
class CMSCommands:
diff --git a/redis/commands/bf/info.py b/redis/commands/bf/info.py
index 24c5419..c4d3e58 100644
--- a/redis/commands/bf/info.py
+++ b/redis/commands/bf/info.py
@@ -68,18 +68,22 @@ class TopKInfo(object):
class TDigestInfo(object):
compression = None
capacity = None
- mergedNodes = None
- unmergedNodes = None
- mergedWeight = None
- unmergedWeight = None
- totalCompressions = None
+ merged_nodes = None
+ unmerged_nodes = None
+ merged_weight = None
+ unmerged_weight = None
+ total_compressions = None
+ sum_weights = None
+ memory_usage = None
def __init__(self, args):
response = dict(zip(map(nativestr, args[::2]), args[1::2]))
self.compression = response["Compression"]
self.capacity = response["Capacity"]
- self.mergedNodes = response["Merged nodes"]
- self.unmergedNodes = response["Unmerged nodes"]
- self.mergedWeight = response["Merged weight"]
- self.unmergedWeight = response["Unmerged weight"]
- self.totalCompressions = response["Total compressions"]
+ self.merged_nodes = response["Merged nodes"]
+ self.unmerged_nodes = response["Unmerged nodes"]
+ self.merged_weight = response["Merged weight"]
+ self.unmerged_weight = response["Unmerged weight"]
+ self.total_compressions = response["Total compressions"]
+ self.sum_weights = response["Sum weights"]
+ self.memory_usage = response["Memory usage"]
diff --git a/redis/commands/bf/utils.py b/redis/commands/bf/utils.py
deleted file mode 100644
index 21dcfa7..0000000
--- a/redis/commands/bf/utils.py
+++ /dev/null
@@ -1,3 +0,0 @@
-def parse_tdigest_quantile(response):
- """Parse TDIGEST.QUANTILE response."""
- return [float(x) for x in response]
diff --git a/tests/test_asyncio/test_bloom.py b/tests/test_asyncio/test_bloom.py
index 162a442..326924c 100644
--- a/tests/test_asyncio/test_bloom.py
+++ b/tests/test_asyncio/test_bloom.py
@@ -1,3 +1,5 @@
+from math import inf
+
import pytest
import redis.asyncio as redis
@@ -322,11 +324,11 @@ async def test_tdigest_reset(modclient: redis.Redis):
# reset on empty histogram
assert await modclient.tdigest().reset("tDigest")
# insert data-points into sketch
- assert await modclient.tdigest().add("tDigest", list(range(10)), [1.0] * 10)
+ assert await modclient.tdigest().add("tDigest", list(range(10)), [1] * 10)
assert await modclient.tdigest().reset("tDigest")
# assert we have 0 unmerged nodes
- assert 0 == (await modclient.tdigest().info("tDigest")).unmergedNodes
+ assert 0 == (await modclient.tdigest().info("tDigest")).unmerged_nodes
@pytest.mark.redismod
@@ -335,14 +337,24 @@ async def test_tdigest_merge(modclient: redis.Redis):
assert await modclient.tdigest().create("to-tDigest", 10)
assert await modclient.tdigest().create("from-tDigest", 10)
# insert data-points into sketch
- assert await modclient.tdigest().add("from-tDigest", [1.0] * 10, [1.0] * 10)
- assert await modclient.tdigest().add("to-tDigest", [2.0] * 10, [10.0] * 10)
+ assert await modclient.tdigest().add("from-tDigest", [1.0] * 10, [1] * 10)
+ assert await modclient.tdigest().add("to-tDigest", [2.0] * 10, [10] * 10)
# merge from-tdigest into to-tdigest
- assert await modclient.tdigest().merge("to-tDigest", "from-tDigest")
+ assert await modclient.tdigest().merge("to-tDigest", 1, "from-tDigest")
# we should now have 110 weight on to-histogram
info = await modclient.tdigest().info("to-tDigest")
- total_weight_to = float(info.mergedWeight) + float(info.unmergedWeight)
+ total_weight_to = float(info.merged_weight) + float(info.unmerged_weight)
assert 110 == total_weight_to
+ # test override
+ assert await modclient.tdigest().create("from-override", 10)
+ assert await modclient.tdigest().create("from-override-2", 10)
+ assert await modclient.tdigest().add("from-override", [3.0] * 10, [10] * 10)
+ assert await modclient.tdigest().add("from-override-2", [4.0] * 10, [10] * 10)
+ assert await modclient.tdigest().merge(
+ "to-tDigest", 2, "from-override", "from-override-2", override=True
+ )
+ assert 3.0 == await modclient.tdigest().min("to-tDigest")
+ assert 4.0 == await modclient.tdigest().max("to-tDigest")
@pytest.mark.redismod
@@ -350,7 +362,7 @@ async def test_tdigest_merge(modclient: redis.Redis):
async def test_tdigest_min_and_max(modclient: redis.Redis):
assert await modclient.tdigest().create("tDigest", 100)
# insert data-points into sketch
- assert await modclient.tdigest().add("tDigest", [1, 2, 3], [1.0] * 3)
+ assert await modclient.tdigest().add("tDigest", [1, 2, 3], [1] * 3)
# min/max
assert 3 == await modclient.tdigest().max("tDigest")
assert 1 == await modclient.tdigest().min("tDigest")
@@ -363,12 +375,12 @@ async def test_tdigest_quantile(modclient: redis.Redis):
assert await modclient.tdigest().create("tDigest", 500)
# insert data-points into sketch
assert await modclient.tdigest().add(
- "tDigest", list([x * 0.01 for x in range(1, 10000)]), [1.0] * 10000
+ "tDigest", list([x * 0.01 for x in range(1, 10000)]), [1] * 10000
)
# assert min min/max have same result as quantile 0 and 1
assert (
await modclient.tdigest().max("tDigest")
- == (await modclient.tdigest().quantile("tDigest", 1.0))[0]
+ == (await modclient.tdigest().quantile("tDigest", 1))[0]
)
assert (
await modclient.tdigest().min("tDigest")
@@ -380,7 +392,7 @@ async def test_tdigest_quantile(modclient: redis.Redis):
# test multiple quantiles
assert await modclient.tdigest().create("t-digest", 100)
- assert await modclient.tdigest().add("t-digest", [1, 2, 3, 4, 5], [1.0] * 5)
+ assert await modclient.tdigest().add("t-digest", [1, 2, 3, 4, 5], [1] * 5)
res = await modclient.tdigest().quantile("t-digest", 0.5, 0.8)
assert [3.0, 5.0] == res
@@ -390,22 +402,67 @@ async def test_tdigest_quantile(modclient: redis.Redis):
async def test_tdigest_cdf(modclient: redis.Redis):
assert await modclient.tdigest().create("tDigest", 100)
# insert data-points into sketch
- assert await modclient.tdigest().add("tDigest", list(range(1, 10)), [1.0] * 10)
- assert 0.1 == round(await modclient.tdigest().cdf("tDigest", 1.0), 1)
- assert 0.9 == round(await modclient.tdigest().cdf("tDigest", 9.0), 1)
+ assert await modclient.tdigest().add("tDigest", list(range(1, 10)), [1] * 10)
+ assert 0.1 == round((await modclient.tdigest().cdf("tDigest", 1.0))[0], 1)
+ assert 0.9 == round((await modclient.tdigest().cdf("tDigest", 9.0))[0], 1)
+ res = await modclient.tdigest().cdf("tDigest", 1.0, 9.0)
+ assert [0.1, 0.9] == [round(x, 1) for x in res]
@pytest.mark.redismod
@pytest.mark.experimental
@skip_ifmodversion_lt("2.4.0", "bf")
-async def test_tdigest_mergestore(modclient: redis.Redis):
- assert await modclient.tdigest().create("sourcekey1", 100)
- assert await modclient.tdigest().create("sourcekey2", 100)
- assert await modclient.tdigest().add("sourcekey1", [10], [1.0])
- assert await modclient.tdigest().add("sourcekey2", [50], [1.0])
- assert await modclient.tdigest().mergestore("dest", 2, "sourcekey1", "sourcekey2")
- assert await modclient.tdigest().max("dest") == 50
- assert await modclient.tdigest().min("dest") == 10
+async def test_tdigest_trimmed_mean(modclient: redis.Redis):
+ assert await modclient.tdigest().create("tDigest", 100)
+ # insert data-points into sketch
+ assert await modclient.tdigest().add("tDigest", list(range(1, 10)), [1] * 10)
+ assert 5 == await modclient.tdigest().trimmed_mean("tDigest", 0.1, 0.9)
+ assert 4.5 == await modclient.tdigest().trimmed_mean("tDigest", 0.4, 0.5)
+
+
+@pytest.mark.redismod
+@pytest.mark.experimental
+async def test_tdigest_rank(modclient: redis.Redis):
+ assert await modclient.tdigest().create("t-digest", 500)
+ assert await modclient.tdigest().add("t-digest", list(range(0, 20)), [1] * 20)
+ assert -1 == (await modclient.tdigest().rank("t-digest", -1))[0]
+ assert 1 == (await modclient.tdigest().rank("t-digest", 0))[0]
+ assert 11 == (await modclient.tdigest().rank("t-digest", 10))[0]
+ assert [-1, 20, 10] == await modclient.tdigest().rank("t-digest", -20, 20, 9)
+
+
+@pytest.mark.redismod
+@pytest.mark.experimental
+async def test_tdigest_revrank(modclient: redis.Redis):
+ assert await modclient.tdigest().create("t-digest", 500)
+ assert await modclient.tdigest().add("t-digest", list(range(0, 20)), [1] * 20)
+ assert -1 == (await modclient.tdigest().revrank("t-digest", 20))[0]
+ assert 20 == (await modclient.tdigest().revrank("t-digest", 0))[0]
+ assert [-1, 20, 10] == await modclient.tdigest().revrank("t-digest", 21, 0, 10)
+
+
+@pytest.mark.redismod
+@pytest.mark.experimental
+async def test_tdigest_byrank(modclient: redis.Redis):
+ assert await modclient.tdigest().create("t-digest", 500)
+ assert await modclient.tdigest().add("t-digest", list(range(1, 11)), [1] * 20)
+ assert 1 == (await modclient.tdigest().byrank("t-digest", 0))[0]
+ assert 10 == (await modclient.tdigest().byrank("t-digest", 9))[0]
+ assert (await modclient.tdigest().byrank("t-digest", 100))[0] == inf
+ with pytest.raises(redis.ResponseError):
+ (await modclient.tdigest().byrank("t-digest", -1))[0]
+
+
+@pytest.mark.redismod
+@pytest.mark.experimental
+async def test_tdigest_byrevrank(modclient: redis.Redis):
+ assert await modclient.tdigest().create("t-digest", 500)
+ assert await modclient.tdigest().add("t-digest", list(range(1, 11)), [1] * 20)
+ assert 10 == (await modclient.tdigest().byrevrank("t-digest", 0))[0]
+ assert 2 == (await modclient.tdigest().byrevrank("t-digest", 9))[0]
+ assert (await modclient.tdigest().byrevrank("t-digest", 100))[0] == -inf
+ with pytest.raises(redis.ResponseError):
+ (await modclient.tdigest().byrevrank("t-digest", -1))[0]
# @pytest.mark.redismod
diff --git a/tests/test_bloom.py b/tests/test_bloom.py
index 54fcd69..1194140 100644
--- a/tests/test_bloom.py
+++ b/tests/test_bloom.py
@@ -1,3 +1,5 @@
+from math import inf
+
import pytest
import redis.commands.bf
@@ -337,11 +339,11 @@ def test_tdigest_reset(client):
# reset on empty histogram
assert client.tdigest().reset("tDigest")
# insert data-points into sketch
- assert client.tdigest().add("tDigest", list(range(10)), [1.0] * 10)
+ assert client.tdigest().add("tDigest", list(range(10)), [1] * 10)
assert client.tdigest().reset("tDigest")
# assert we have 0 unmerged nodes
- assert 0 == client.tdigest().info("tDigest").unmergedNodes
+ assert 0 == client.tdigest().info("tDigest").unmerged_nodes
@pytest.mark.redismod
@@ -350,14 +352,24 @@ def test_tdigest_merge(client):
assert client.tdigest().create("to-tDigest", 10)
assert client.tdigest().create("from-tDigest", 10)
# insert data-points into sketch
- assert client.tdigest().add("from-tDigest", [1.0] * 10, [1.0] * 10)
- assert client.tdigest().add("to-tDigest", [2.0] * 10, [10.0] * 10)
+ assert client.tdigest().add("from-tDigest", [1.0] * 10, [1] * 10)
+ assert client.tdigest().add("to-tDigest", [2.0] * 10, [10] * 10)
# merge from-tdigest into to-tdigest
- assert client.tdigest().merge("to-tDigest", "from-tDigest")
+ assert client.tdigest().merge("to-tDigest", 1, "from-tDigest")
# we should now have 110 weight on to-histogram
info = client.tdigest().info("to-tDigest")
- total_weight_to = float(info.mergedWeight) + float(info.unmergedWeight)
+ total_weight_to = float(info.merged_weight) + float(info.unmerged_weight)
assert 110 == total_weight_to
+ # test override
+ assert client.tdigest().create("from-override", 10)
+ assert client.tdigest().create("from-override-2", 10)
+ assert client.tdigest().add("from-override", [3.0] * 10, [10] * 10)
+ assert client.tdigest().add("from-override-2", [4.0] * 10, [10] * 10)
+ assert client.tdigest().merge(
+ "to-tDigest", 2, "from-override", "from-override-2", override=True
+ )
+ assert 3.0 == client.tdigest().min("to-tDigest")
+ assert 4.0 == client.tdigest().max("to-tDigest")
@pytest.mark.redismod
@@ -365,7 +377,7 @@ def test_tdigest_merge(client):
def test_tdigest_min_and_max(client):
assert client.tdigest().create("tDigest", 100)
# insert data-points into sketch
- assert client.tdigest().add("tDigest", [1, 2, 3], [1.0] * 3)
+ assert client.tdigest().add("tDigest", [1, 2, 3], [1] * 3)
# min/max
assert 3 == client.tdigest().max("tDigest")
assert 1 == client.tdigest().min("tDigest")
@@ -378,7 +390,7 @@ def test_tdigest_quantile(client):
assert client.tdigest().create("tDigest", 500)
# insert data-points into sketch
assert client.tdigest().add(
- "tDigest", list([x * 0.01 for x in range(1, 10000)]), [1.0] * 10000
+ "tDigest", list([x * 0.01 for x in range(1, 10000)]), [1] * 10000
)
# assert min min/max have same result as quantile 0 and 1
res = client.tdigest().quantile("tDigest", 1.0)
@@ -391,7 +403,7 @@ def test_tdigest_quantile(client):
# test multiple quantiles
assert client.tdigest().create("t-digest", 100)
- assert client.tdigest().add("t-digest", [1, 2, 3, 4, 5], [1.0] * 5)
+ assert client.tdigest().add("t-digest", [1, 2, 3, 4, 5], [1] * 5)
assert [3.0, 5.0] == client.tdigest().quantile("t-digest", 0.5, 0.8)
@@ -400,9 +412,11 @@ def test_tdigest_quantile(client):
def test_tdigest_cdf(client):
assert client.tdigest().create("tDigest", 100)
# insert data-points into sketch
- assert client.tdigest().add("tDigest", list(range(1, 10)), [1.0] * 10)
- assert 0.1 == round(client.tdigest().cdf("tDigest", 1.0), 1)
- assert 0.9 == round(client.tdigest().cdf("tDigest", 9.0), 1)
+ assert client.tdigest().add("tDigest", list(range(1, 10)), [1] * 10)
+ assert 0.1 == round(client.tdigest().cdf("tDigest", 1.0)[0], 1)
+ assert 0.9 == round(client.tdigest().cdf("tDigest", 9.0)[0], 1)
+ res = client.tdigest().cdf("tDigest", 1.0, 9.0)
+ assert [0.1, 0.9] == [round(x, 1) for x in res]
@pytest.mark.redismod
@@ -411,22 +425,54 @@ def test_tdigest_cdf(client):
def test_tdigest_trimmed_mean(client):
assert client.tdigest().create("tDigest", 100)
# insert data-points into sketch
- assert client.tdigest().add("tDigest", list(range(1, 10)), [1.0] * 10)
+ assert client.tdigest().add("tDigest", list(range(1, 10)), [1] * 10)
assert 5 == client.tdigest().trimmed_mean("tDigest", 0.1, 0.9)
assert 4.5 == client.tdigest().trimmed_mean("tDigest", 0.4, 0.5)
@pytest.mark.redismod
@pytest.mark.experimental
-@skip_ifmodversion_lt("2.4.0", "bf")
-def test_tdigest_mergestore(client):
- assert client.tdigest().create("sourcekey1", 100)
- assert client.tdigest().create("sourcekey2", 100)
- assert client.tdigest().add("sourcekey1", [10], [1.0])
- assert client.tdigest().add("sourcekey2", [50], [1.0])
- assert client.tdigest().mergestore("destkey", 2, "sourcekey1", "sourcekey2")
- assert client.tdigest().max("destkey") == 50
- assert client.tdigest().min("destkey") == 10
+def test_tdigest_rank(client):
+ assert client.tdigest().create("t-digest", 500)
+ assert client.tdigest().add("t-digest", list(range(0, 20)), [1] * 20)
+ assert -1 == client.tdigest().rank("t-digest", -1)[0]
+ assert 1 == client.tdigest().rank("t-digest", 0)[0]
+ assert 11 == client.tdigest().rank("t-digest", 10)[0]
+ assert [-1, 20, 10] == client.tdigest().rank("t-digest", -20, 20, 9)
+
+
+@pytest.mark.redismod
+@pytest.mark.experimental
+def test_tdigest_revrank(client):
+ assert client.tdigest().create("t-digest", 500)
+ assert client.tdigest().add("t-digest", list(range(0, 20)), [1] * 20)
+ assert -1 == client.tdigest().revrank("t-digest", 20)[0]
+ assert 20 == client.tdigest().revrank("t-digest", 0)[0]
+ assert [-1, 20, 10] == client.tdigest().revrank("t-digest", 21, 0, 10)
+
+
+@pytest.mark.redismod
+@pytest.mark.experimental
+def test_tdigest_byrank(client):
+ assert client.tdigest().create("t-digest", 500)
+ assert client.tdigest().add("t-digest", list(range(1, 11)), [1] * 20)
+ assert 1 == client.tdigest().byrank("t-digest", 0)[0]
+ assert 10 == client.tdigest().byrank("t-digest", 9)[0]
+ assert client.tdigest().byrank("t-digest", 100)[0] == inf
+ with pytest.raises(redis.ResponseError):
+ client.tdigest().byrank("t-digest", -1)[0]
+
+
+@pytest.mark.redismod
+@pytest.mark.experimental
+def test_tdigest_byrevrank(client):
+ assert client.tdigest().create("t-digest", 500)
+ assert client.tdigest().add("t-digest", list(range(1, 11)), [1] * 20)
+ assert 10 == client.tdigest().byrevrank("t-digest", 0)[0]
+ assert 2 == client.tdigest().byrevrank("t-digest", 9)[0]
+ assert client.tdigest().byrevrank("t-digest", 100)[0] == -inf
+ with pytest.raises(redis.ResponseError):
+ client.tdigest().byrevrank("t-digest", -1)[0]
# @pytest.mark.redismod