Skip to content

Commit bdae789

Browse files
dvora-hchayim
andauthored
Add dialect support for RediSearch queries (#2071)
* Add dialect support for RediSearch queries * type hints Co-authored-by: Chayim <[email protected]>
1 parent 0a5e486 commit bdae789

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

redis/commands/search/query.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def __init__(self, query_string):
3535
self._highlight_fields = []
3636
self._language = None
3737
self._expander = None
38+
self._dialect = None
3839

3940
def query_string(self):
4041
"""Return the query string of this query only."""
@@ -202,6 +203,8 @@ def _get_args_tags(self):
202203
args += ["LANGUAGE", self._language]
203204
if self._expander:
204205
args += ["EXPANDER", self._expander]
206+
if self._dialect:
207+
args += ["DIALECT", self._dialect]
205208

206209
return args
207210

@@ -288,6 +291,15 @@ def expander(self, expander):
288291
self._expander = expander
289292
return self
290293

294+
def dialect(self, dialect: int) -> "Query":
295+
"""
296+
Add a dialect field to the query.
297+
298+
- **dialect** - dialect version to execute the query under
299+
"""
300+
self._dialect = dialect
301+
return self
302+
291303

292304
class Filter:
293305
def __init__(self, keyword, field, *args):

tests/test_search.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,3 +1631,48 @@ def test_search_commands_in_pipeline(client):
16311631
assert "foo baz" == res[3][2]
16321632
assert res[3][5] is None
16331633
assert res[3][3] == res[3][6] == ["txt", "foo bar"]
1634+
1635+
1636+
@pytest.mark.redismod
1637+
@pytest.mark.onlynoncluster
1638+
@skip_ifmodversion_lt("2.4.3", "search")
1639+
def test_dialect_config(modclient: redis.Redis):
1640+
assert modclient.ft().config_get("DEFAULT_DIALECT") == {"DEFAULT_DIALECT": "1"}
1641+
assert modclient.ft().config_set("DEFAULT_DIALECT", 2)
1642+
assert modclient.ft().config_get("DEFAULT_DIALECT") == {"DEFAULT_DIALECT": "2"}
1643+
with pytest.raises(redis.ResponseError):
1644+
modclient.ft().config_set("DEFAULT_DIALECT", 0)
1645+
1646+
1647+
@pytest.mark.redismod
1648+
@skip_ifmodversion_lt("2.4.3", "search")
1649+
def test_dialect(modclient: redis.Redis):
1650+
modclient.ft().create_index(
1651+
(
1652+
TagField("title"),
1653+
TextField("t1"),
1654+
TextField("t2"),
1655+
NumericField("num"),
1656+
VectorField(
1657+
"v", "HNSW", {"TYPE": "FLOAT32", "DIM": 1, "DISTANCE_METRIC": "COSINE"}
1658+
),
1659+
)
1660+
)
1661+
modclient.hset("h", "t1", "hello")
1662+
with pytest.raises(redis.ResponseError) as err:
1663+
modclient.ft().explain(Query("(*)").dialect(1))
1664+
assert "Syntax error" in str(err)
1665+
assert "WILDCARD" in modclient.ft().explain(Query("(*)").dialect(2))
1666+
1667+
with pytest.raises(redis.ResponseError) as err:
1668+
modclient.ft().explain(Query("$hello").dialect(1))
1669+
assert "Syntax error" in str(err)
1670+
q = Query("$hello").dialect(2)
1671+
expected = "UNION {\n hello\n +hello(expanded)\n}\n"
1672+
assert expected in modclient.ft().explain(q, query_params={"hello": "hello"})
1673+
1674+
expected = "NUMERIC {0.000000 <= @num <= 10.000000}\n"
1675+
assert expected in modclient.ft().explain(Query("@title:(@num:[0 10])").dialect(1))
1676+
with pytest.raises(redis.ResponseError) as err:
1677+
modclient.ft().explain(Query("@title:(@num:[0 10])").dialect(2))
1678+
assert "Syntax error" in str(err)

0 commit comments

Comments
 (0)