Skip to content

Commit

Permalink
Merge branch 'master' into vecsim-example
Browse files Browse the repository at this point in the history
  • Loading branch information
dvora-h committed Apr 4, 2022
2 parents 0c2f0c4 + 876cafc commit 77bc880
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 7 deletions.
1 change: 1 addition & 0 deletions dev_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
click==8.0.4
black==21.11b1
flake8==4.0.1
flynt~=0.69.0
Expand Down
11 changes: 11 additions & 0 deletions redis/commands/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,17 @@ class RedisClusterCommands(
r.cluster_info(target_nodes=RedisCluster.ALL_NODES)
"""

def cluster_myid(self, target_node):
"""
Returns the node’s id.
:target_node: 'ClusterNode'
The node to execute the command on
For more information check https://redis.io/commands/cluster-myid/
"""
return self.execute_command("CLUSTER MYID", target_nodes=target_node)

def cluster_addslots(self, target_node, *slots):
"""
Assign new hash slots to receiving node. Sends to specified node.
Expand Down
12 changes: 12 additions & 0 deletions redis/commands/search/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, query_string):
self._highlight_fields = []
self._language = None
self._expander = None
self._dialect = None

def query_string(self):
"""Return the query string of this query only."""
Expand Down Expand Up @@ -202,6 +203,8 @@ def _get_args_tags(self):
args += ["LANGUAGE", self._language]
if self._expander:
args += ["EXPANDER", self._expander]
if self._dialect:
args += ["DIALECT", self._dialect]

return args

Expand Down Expand Up @@ -288,6 +291,15 @@ def expander(self, expander):
self._expander = expander
return self

def dialect(self, dialect: int) -> "Query":
"""
Add a dialect field to the query.
- **dialect** - dialect version to execute the query under
"""
self._dialect = dialect
return self


class Filter:
def __init__(self, keyword, field, *args):
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
async-timeout>=4.0.2
deprecated>=1.2.3
packaging>=20.4
typing-extensions
typing-extensions; python_version<"3.8"
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
long_description_content_type="text/markdown",
keywords=["Redis", "key-value store", "database"],
license="MIT",
version="4.2.0",
version="4.2.1",
packages=find_packages(
include=[
"redis",
Expand All @@ -35,7 +35,7 @@
"deprecated>=1.2.3",
"packaging>=20.4",
'importlib-metadata >= 1.0; python_version < "3.8"',
"typing-extensions",
'typing-extensions; python_version<"3.8"',
"async-timeout>=4.0.2",
],
classifiers=[
Expand Down
5 changes: 5 additions & 0 deletions tests/test_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,11 @@ def test_cluster_pubsub_numsub(self, r):
channels = [(b"foo", 1), (b"bar", 2), (b"baz", 3)]
assert r.pubsub_numsub("foo", "bar", "baz", target_nodes="all") == channels

def test_cluster_myid(self, r):
node = r.get_random_node()
myid = r.cluster_myid(node)
assert len(myid) == 40

def test_cluster_slots(self, r):
mock_all_nodes_resp(r, default_cluster_slots)
cluster_slots = r.cluster_slots()
Expand Down
54 changes: 50 additions & 4 deletions tests/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,8 @@ def test_vector_field(modclient):
modclient.hset("b", "v", "aaaabaaa")
modclient.hset("c", "v", "aaaaabaa")

q = Query("*=>[KNN 2 @v $vec]").return_field("__v_score").sort_by("__v_score", True)
query = "*=>[KNN 2 @v $vec]"
q = Query(query).return_field("__v_score").sort_by("__v_score", True).dialect(2)
res = modclient.ft().search(q, query_params={"vec": "aaaaaaaa"})

assert "a" == res.docs[0].id
Expand Down Expand Up @@ -1572,7 +1573,7 @@ def test_text_params(modclient):
modclient.ft().add_document("doc3", name="Carol")

params_dict = {"name1": "Alice", "name2": "Bob"}
q = Query("@name:($name1 | $name2 )")
q = Query("@name:($name1 | $name2 )").dialect(2)
res = modclient.ft().search(q, query_params=params_dict)
assert 2 == res.total
assert "doc1" == res.docs[0].id
Expand All @@ -1589,7 +1590,7 @@ def test_numeric_params(modclient):
modclient.ft().add_document("doc3", numval=103)

params_dict = {"min": 101, "max": 102}
q = Query("@numval:[$min $max]")
q = Query("@numval:[$min $max]").dialect(2)
res = modclient.ft().search(q, query_params=params_dict)

assert 2 == res.total
Expand All @@ -1607,7 +1608,7 @@ def test_geo_params(modclient):
modclient.ft().add_document("doc3", g="29.68746, 34.94882")

params_dict = {"lat": "34.95126", "lon": "29.69465", "radius": 1000, "units": "km"}
q = Query("@g:[$lon $lat $radius $units]")
q = Query("@g:[$lon $lat $radius $units]").dialect(2)
res = modclient.ft().search(q, query_params=params_dict)
assert 3 == res.total
assert "doc1" == res.docs[0].id
Expand All @@ -1631,3 +1632,48 @@ def test_search_commands_in_pipeline(client):
assert "foo baz" == res[3][2]
assert res[3][5] is None
assert res[3][3] == res[3][6] == ["txt", "foo bar"]


@pytest.mark.redismod
@pytest.mark.onlynoncluster
@skip_ifmodversion_lt("2.4.3", "search")
def test_dialect_config(modclient: redis.Redis):
assert modclient.ft().config_get("DEFAULT_DIALECT") == {"DEFAULT_DIALECT": "1"}
assert modclient.ft().config_set("DEFAULT_DIALECT", 2)
assert modclient.ft().config_get("DEFAULT_DIALECT") == {"DEFAULT_DIALECT": "2"}
with pytest.raises(redis.ResponseError):
modclient.ft().config_set("DEFAULT_DIALECT", 0)


@pytest.mark.redismod
@skip_ifmodversion_lt("2.4.3", "search")
def test_dialect(modclient: redis.Redis):
modclient.ft().create_index(
(
TagField("title"),
TextField("t1"),
TextField("t2"),
NumericField("num"),
VectorField(
"v", "HNSW", {"TYPE": "FLOAT32", "DIM": 1, "DISTANCE_METRIC": "COSINE"}
),
)
)
modclient.hset("h", "t1", "hello")
with pytest.raises(redis.ResponseError) as err:
modclient.ft().explain(Query("(*)").dialect(1))
assert "Syntax error" in str(err)
assert "WILDCARD" in modclient.ft().explain(Query("(*)").dialect(2))

with pytest.raises(redis.ResponseError) as err:
modclient.ft().explain(Query("$hello").dialect(1))
assert "Syntax error" in str(err)
q = Query("$hello").dialect(2)
expected = "UNION {\n hello\n +hello(expanded)\n}\n"
assert expected in modclient.ft().explain(q, query_params={"hello": "hello"})

expected = "NUMERIC {0.000000 <= @num <= 10.000000}\n"
assert expected in modclient.ft().explain(Query("@title:(@num:[0 10])").dialect(1))
with pytest.raises(redis.ResponseError) as err:
modclient.ft().explain(Query("@title:(@num:[0 10])").dialect(2))
assert "Syntax error" in str(err)

0 comments on commit 77bc880

Please sign in to comment.