diff --git a/redis/commands/json/__init__.py b/redis/commands/json/__init__.py index 77fb21c39f..4f2a0c5ffc 100644 --- a/redis/commands/json/__init__.py +++ b/redis/commands/json/__init__.py @@ -38,6 +38,7 @@ def __init__( "JSON.GET": self._decode, "JSON.MGET": bulk_of_jsons(self._decode), "JSON.SET": lambda r: r and nativestr(r) == "OK", + "JSON.MSET": lambda r: r and nativestr(r) == "OK", "JSON.MERGE": lambda r: r and nativestr(r) == "OK", "JSON.NUMINCRBY": self._decode, "JSON.NUMMULTBY": self._decode, diff --git a/redis/commands/json/commands.py b/redis/commands/json/commands.py index 5da9245a95..3465bea1e6 100644 --- a/redis/commands/json/commands.py +++ b/redis/commands/json/commands.py @@ -1,6 +1,6 @@ import os from json import JSONDecodeError, loads -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional, Tuple, Union from redis.exceptions import DataError from redis.utils import deprecated_function @@ -253,6 +253,23 @@ def set( pieces.append("XX") return self.execute_command("JSON.SET", *pieces) + def mset(self, triplets: List[Tuple[str, str, JsonType]]) -> Optional[str]: + """ + Set the JSON value at key ``name`` under the ``path`` to ``obj`` + for one or more keys. + + ``triplets`` is a list of one or more triplets of key, path, value. + + For the purpose of using this within a pipeline, this command is also + aliased to JSON.MSET. + + For more information see `JSON.MSET `_. + """ + pieces = [] + for triplet in triplets: + pieces.extend([triplet[0], str(triplet[1]), self._encode(triplet[2])]) + return self.execute_command("JSON.MSET", *pieces) + def merge( self, name: str, diff --git a/tests/test_asyncio/test_json.py b/tests/test_asyncio/test_json.py index 7334399df4..12bdacdb9a 100644 --- a/tests/test_asyncio/test_json.py +++ b/tests/test_asyncio/test_json.py @@ -109,6 +109,17 @@ async def test_mgetshouldsucceed(modclient: redis.Redis): assert await modclient.json().mget([1, 2], Path.root_path()) == [1, 2] +@pytest.mark.redismod +@skip_ifmodversion_lt("2.6.0", "ReJSON") # todo: update after the release +async def test_mset(modclient: redis.Redis): + await modclient.json().mset( + [("1", Path.root_path(), 1), ("2", Path.root_path(), 2)] + ) + + assert await modclient.json().mget(["1"], Path.root_path()) == [1] + assert await modclient.json().mget(["1", "2"], Path.root_path()) == [1, 2] + + @pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release async def test_clear(modclient: redis.Redis): diff --git a/tests/test_json.py b/tests/test_json.py index 0a85998205..c41ad5e2e1 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -115,6 +115,15 @@ def test_mgetshouldsucceed(client): assert client.json().mget([1, 2], Path.root_path()) == [1, 2] +@pytest.mark.redismod +@skip_ifmodversion_lt("2.6.0", "ReJSON") # todo: update after the release +def test_mset(client): + client.json().mset([("1", Path.root_path(), 1), ("2", Path.root_path(), 2)]) + + assert client.json().mget(["1"], Path.root_path()) == [1] + assert client.json().mget(["1", "2"], Path.root_path()) == [1, 2] + + @pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release def test_clear(client):