Skip to content

Commit 5bf9034

Browse files
authored
Add pipeline support for search (#2038)
1 parent 1f2259f commit 5bf9034

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

Diff for: redis/commands/search/__init__.py

+25-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import redis
2+
13
from .commands import SearchCommands
24

35

@@ -17,7 +19,7 @@ def __init__(self, client, chunk_size=1000):
1719

1820
self.client = client
1921
self.execute_command = client.execute_command
20-
self.pipeline = client.pipeline(transaction=False, shard_hint=None)
22+
self._pipeline = client.pipeline(transaction=False, shard_hint=None)
2123
self.total = 0
2224
self.chunk_size = chunk_size
2325
self.current_chunk = 0
@@ -42,7 +44,7 @@ def add_document(
4244
"""
4345
self.client._add_document(
4446
doc_id,
45-
conn=self.pipeline,
47+
conn=self._pipeline,
4648
nosave=nosave,
4749
score=score,
4850
payload=payload,
@@ -67,7 +69,7 @@ def add_document_hash(
6769
"""
6870
self.client._add_document_hash(
6971
doc_id,
70-
conn=self.pipeline,
72+
conn=self._pipeline,
7173
score=score,
7274
replace=replace,
7375
)
@@ -80,7 +82,7 @@ def commit(self):
8082
"""
8183
Manually commit and flush the batch indexing query
8284
"""
83-
self.pipeline.execute()
85+
self._pipeline.execute()
8486
self.current_chunk = 0
8587

8688
def __init__(self, client, index_name="idx"):
@@ -90,7 +92,25 @@ def __init__(self, client, index_name="idx"):
9092
9193
If conn is not None, we employ an already existing redis connection
9294
"""
95+
self.MODULE_CALLBACKS = {}
9396
self.client = client
9497
self.index_name = index_name
9598
self.execute_command = client.execute_command
96-
self.pipeline = client.pipeline
99+
self._pipeline = client.pipeline
100+
101+
def pipeline(self, transaction=True, shard_hint=None):
102+
"""Creates a pipeline for the SEARCH module, that can be used for executing
103+
SEARCH commands, as well as classic core commands.
104+
"""
105+
p = Pipeline(
106+
connection_pool=self.client.connection_pool,
107+
response_callbacks=self.MODULE_CALLBACKS,
108+
transaction=transaction,
109+
shard_hint=shard_hint,
110+
)
111+
p.index_name = self.index_name
112+
return p
113+
114+
115+
class Pipeline(SearchCommands, redis.client.Pipeline):
116+
"""Pipeline for the module."""

Diff for: redis/commands/search/commands.py

+20-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import time
33
from typing import Dict, Union
44

5+
from redis.client import Pipeline
6+
57
from ..helpers import parse_to_dict
68
from ._util import to_string
79
from .aggregation import AggregateRequest, AggregateResult, Cursor
@@ -186,8 +188,6 @@ def _add_document(
186188
"""
187189
Internal add_document used for both batch and single doc indexing
188190
"""
189-
if conn is None:
190-
conn = self.client
191191

192192
if partial or no_create:
193193
replace = True
@@ -208,7 +208,11 @@ def _add_document(
208208
args += ["LANGUAGE", language]
209209
args.append("FIELDS")
210210
args += list(itertools.chain(*fields.items()))
211-
return conn.execute_command(*args)
211+
212+
if conn is not None:
213+
return conn.execute_command(*args)
214+
215+
return self.execute_command(*args)
212216

213217
def _add_document_hash(
214218
self,
@@ -221,8 +225,6 @@ def _add_document_hash(
221225
"""
222226
Internal add_document_hash used for both batch and single doc indexing
223227
"""
224-
if conn is None:
225-
conn = self.client
226228

227229
args = [ADDHASH_CMD, self.index_name, doc_id, score]
228230

@@ -232,7 +234,10 @@ def _add_document_hash(
232234
if language:
233235
args += ["LANGUAGE", language]
234236

235-
return conn.execute_command(*args)
237+
if conn is not None:
238+
return conn.execute_command(*args)
239+
240+
return self.execute_command(*args)
236241

237242
def add_document(
238243
self,
@@ -331,12 +336,13 @@ def delete_document(self, doc_id, conn=None, delete_actual_document=False):
331336
For more information: https://oss.redis.com/redisearch/Commands/#ftdel
332337
""" # noqa
333338
args = [DEL_CMD, self.index_name, doc_id]
334-
if conn is None:
335-
conn = self.client
336339
if delete_actual_document:
337340
args.append("DD")
338341

339-
return conn.execute_command(*args)
342+
if conn is not None:
343+
return conn.execute_command(*args)
344+
345+
return self.execute_command(*args)
340346

341347
def load_document(self, id):
342348
"""
@@ -364,7 +370,7 @@ def get(self, *ids):
364370
For more information https://oss.redis.com/redisearch/Commands/#ftget
365371
"""
366372

367-
return self.client.execute_command(MGET_CMD, self.index_name, *ids)
373+
return self.execute_command(MGET_CMD, self.index_name, *ids)
368374

369375
def info(self):
370376
"""
@@ -374,7 +380,7 @@ def info(self):
374380
For more information https://oss.redis.com/redisearch/Commands/#ftinfo
375381
"""
376382

377-
res = self.client.execute_command(INFO_CMD, self.index_name)
383+
res = self.execute_command(INFO_CMD, self.index_name)
378384
it = map(to_string, res)
379385
return dict(zip(it, it))
380386

@@ -423,6 +429,9 @@ def search(
423429
st = time.time()
424430
res = self.execute_command(SEARCH_CMD, *args)
425431

432+
if isinstance(res, Pipeline):
433+
return res
434+
426435
return Result(
427436
res,
428437
not query._no_content,

Diff for: tests/test_search.py

+18
Original file line numberDiff line numberDiff line change
@@ -1577,3 +1577,21 @@ def test_geo_params(modclient):
15771577
assert "doc1" == res.docs[0].id
15781578
assert "doc2" == res.docs[1].id
15791579
assert "doc3" == res.docs[2].id
1580+
1581+
1582+
@pytest.mark.redismod
1583+
def test_search_commands_in_pipeline(client):
1584+
p = client.ft().pipeline()
1585+
p.create_index((TextField("txt"),))
1586+
p.add_document("doc1", payload="foo baz", txt="foo bar")
1587+
p.add_document("doc2", txt="foo bar")
1588+
q = Query("foo bar").with_payloads()
1589+
p.search(q)
1590+
res = p.execute()
1591+
assert res[:3] == ["OK", "OK", "OK"]
1592+
assert 2 == res[3][0]
1593+
assert "doc1" == res[3][1]
1594+
assert "doc2" == res[3][4]
1595+
assert "foo baz" == res[3][2]
1596+
assert res[3][5] is None
1597+
assert res[3][3] == res[3][6] == ["txt", "foo bar"]

0 commit comments

Comments
 (0)