coredis 5.5.0__cp313-cp313-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 22fe76227e35f92ab5c3__mypyc.cpython-313-darwin.so +0 -0
- coredis/__init__.py +42 -0
- coredis/_enum.py +42 -0
- coredis/_json.py +11 -0
- coredis/_packer.cpython-313-darwin.so +0 -0
- coredis/_packer.py +71 -0
- coredis/_protocols.py +50 -0
- coredis/_py_311_typing.py +20 -0
- coredis/_py_312_typing.py +17 -0
- coredis/_sidecar.py +114 -0
- coredis/_utils.cpython-313-darwin.so +0 -0
- coredis/_utils.py +440 -0
- coredis/_version.py +34 -0
- coredis/_version.pyi +1 -0
- coredis/cache.py +801 -0
- coredis/client/__init__.py +6 -0
- coredis/client/basic.py +1240 -0
- coredis/client/cluster.py +1265 -0
- coredis/commands/__init__.py +64 -0
- coredis/commands/_key_spec.py +517 -0
- coredis/commands/_utils.py +108 -0
- coredis/commands/_validators.py +159 -0
- coredis/commands/_wrappers.py +175 -0
- coredis/commands/bitfield.py +110 -0
- coredis/commands/constants.py +662 -0
- coredis/commands/core.py +8484 -0
- coredis/commands/function.py +408 -0
- coredis/commands/monitor.py +168 -0
- coredis/commands/pubsub.py +905 -0
- coredis/commands/request.py +108 -0
- coredis/commands/script.py +296 -0
- coredis/commands/sentinel.py +246 -0
- coredis/config.py +50 -0
- coredis/connection.py +906 -0
- coredis/constants.cpython-313-darwin.so +0 -0
- coredis/constants.py +37 -0
- coredis/credentials.py +45 -0
- coredis/exceptions.py +360 -0
- coredis/experimental/__init__.py +1 -0
- coredis/globals.py +23 -0
- coredis/modules/__init__.py +121 -0
- coredis/modules/autocomplete.py +138 -0
- coredis/modules/base.py +262 -0
- coredis/modules/filters.py +1319 -0
- coredis/modules/graph.py +362 -0
- coredis/modules/json.py +691 -0
- coredis/modules/response/__init__.py +0 -0
- coredis/modules/response/_callbacks/__init__.py +0 -0
- coredis/modules/response/_callbacks/autocomplete.py +42 -0
- coredis/modules/response/_callbacks/graph.py +237 -0
- coredis/modules/response/_callbacks/json.py +21 -0
- coredis/modules/response/_callbacks/search.py +221 -0
- coredis/modules/response/_callbacks/timeseries.py +158 -0
- coredis/modules/response/types.py +179 -0
- coredis/modules/search.py +1089 -0
- coredis/modules/timeseries.py +1139 -0
- coredis/parser.cpython-313-darwin.so +0 -0
- coredis/parser.py +344 -0
- coredis/pipeline.py +1225 -0
- coredis/pool/__init__.py +11 -0
- coredis/pool/basic.py +453 -0
- coredis/pool/cluster.py +517 -0
- coredis/pool/nodemanager.py +340 -0
- coredis/py.typed +0 -0
- coredis/recipes/__init__.py +0 -0
- coredis/recipes/credentials/__init__.py +5 -0
- coredis/recipes/credentials/iam_provider.py +63 -0
- coredis/recipes/locks/__init__.py +5 -0
- coredis/recipes/locks/extend.lua +17 -0
- coredis/recipes/locks/lua_lock.py +281 -0
- coredis/recipes/locks/release.lua +10 -0
- coredis/response/__init__.py +5 -0
- coredis/response/_callbacks/__init__.py +538 -0
- coredis/response/_callbacks/acl.py +32 -0
- coredis/response/_callbacks/cluster.py +183 -0
- coredis/response/_callbacks/command.py +86 -0
- coredis/response/_callbacks/connection.py +31 -0
- coredis/response/_callbacks/geo.py +58 -0
- coredis/response/_callbacks/hash.py +85 -0
- coredis/response/_callbacks/keys.py +59 -0
- coredis/response/_callbacks/module.py +33 -0
- coredis/response/_callbacks/script.py +85 -0
- coredis/response/_callbacks/sentinel.py +179 -0
- coredis/response/_callbacks/server.py +241 -0
- coredis/response/_callbacks/sets.py +44 -0
- coredis/response/_callbacks/sorted_set.py +204 -0
- coredis/response/_callbacks/streams.py +185 -0
- coredis/response/_callbacks/strings.py +70 -0
- coredis/response/_callbacks/vector_sets.py +159 -0
- coredis/response/_utils.py +33 -0
- coredis/response/types.py +416 -0
- coredis/retry.py +233 -0
- coredis/sentinel.py +477 -0
- coredis/stream.py +369 -0
- coredis/tokens.py +2286 -0
- coredis/typing.py +593 -0
- coredis-5.5.0.dist-info/METADATA +211 -0
- coredis-5.5.0.dist-info/RECORD +100 -0
- coredis-5.5.0.dist-info/WHEEL +6 -0
- coredis-5.5.0.dist-info/licenses/LICENSE +23 -0
|
@@ -0,0 +1,1089 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import itertools
|
|
5
|
+
from collections import OrderedDict
|
|
6
|
+
from datetime import timedelta
|
|
7
|
+
|
|
8
|
+
from deprecated.sphinx import versionadded
|
|
9
|
+
|
|
10
|
+
from ..commands._utils import normalized_milliseconds, normalized_seconds
|
|
11
|
+
from ..commands._wrappers import ClusterCommandConfig
|
|
12
|
+
from ..commands.constants import CommandGroup, CommandName, NodeFlag
|
|
13
|
+
from ..commands.request import CommandRequest
|
|
14
|
+
from ..response._callbacks import (
|
|
15
|
+
AnyStrCallback,
|
|
16
|
+
ClusterEnsureConsistent,
|
|
17
|
+
ClusterMergeSets,
|
|
18
|
+
DictCallback,
|
|
19
|
+
IntCallback,
|
|
20
|
+
SetCallback,
|
|
21
|
+
SimpleStringCallback,
|
|
22
|
+
)
|
|
23
|
+
from ..tokens import PrefixToken, PureToken
|
|
24
|
+
from ..typing import (
|
|
25
|
+
AnyStr,
|
|
26
|
+
CommandArgList,
|
|
27
|
+
KeyT,
|
|
28
|
+
Literal,
|
|
29
|
+
Mapping,
|
|
30
|
+
Parameters,
|
|
31
|
+
ResponsePrimitive,
|
|
32
|
+
ResponseType,
|
|
33
|
+
StringT,
|
|
34
|
+
ValueT,
|
|
35
|
+
)
|
|
36
|
+
from .base import Module, ModuleGroup, module_command
|
|
37
|
+
from .response._callbacks.search import (
|
|
38
|
+
AggregationResultCallback,
|
|
39
|
+
SearchConfigCallback,
|
|
40
|
+
SearchResultCallback,
|
|
41
|
+
SpellCheckCallback,
|
|
42
|
+
)
|
|
43
|
+
from .response.types import SearchAggregationResult, SearchResult
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class RediSearch(Module[AnyStr]):
|
|
47
|
+
NAME = "search"
|
|
48
|
+
FULL_NAME = "RediSearch"
|
|
49
|
+
DESCRIPTION = """RedisSearch is a Redis module that enables querying, secondary
|
|
50
|
+
indexing, and full-text search for Redis. These features enable multi-field queries,
|
|
51
|
+
aggregation, exact phrase matching, numeric filtering, geo filtering and vector
|
|
52
|
+
similarity semantic search on top of text queries."""
|
|
53
|
+
DOCUMENTATION_URL = "https://redis.io/docs/stack/search"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclasses.dataclass
|
|
57
|
+
class Field:
|
|
58
|
+
"""
|
|
59
|
+
Field definition to be used in :meth:`~coredis.modules.Search.create` &
|
|
60
|
+
:meth:`~coredis.modules.Search.alter`
|
|
61
|
+
|
|
62
|
+
For more details refer to the documentation for
|
|
63
|
+
`FT.CREATE <https://redis.io/commands/ft.create/>`__
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
#: Name of the field. For hashes, this is a field name within the hash.
|
|
67
|
+
#: For JSON, this is a JSON Path expression.
|
|
68
|
+
name: StringT
|
|
69
|
+
#: Type of field
|
|
70
|
+
type: Literal[
|
|
71
|
+
PureToken.TEXT,
|
|
72
|
+
PureToken.TAG,
|
|
73
|
+
PureToken.NUMERIC,
|
|
74
|
+
PureToken.GEO,
|
|
75
|
+
PureToken.VECTOR,
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
#: Defines the alias associated to :paramref:`name`.
|
|
79
|
+
#: For example, you can use this feature to alias a complex
|
|
80
|
+
#: JSONPath expression with more memorable (and easier to type) name.
|
|
81
|
+
alias: StringT | None = None
|
|
82
|
+
#: Whether to optimize for sorting.
|
|
83
|
+
sortable: bool | None = None
|
|
84
|
+
#: Whether to use the unnormalized form of the field for sorting.
|
|
85
|
+
unf: bool | None = None
|
|
86
|
+
#: Whether to disable stemming for this field.
|
|
87
|
+
nostem: bool | None = None
|
|
88
|
+
#: Skip indexing this field
|
|
89
|
+
noindex: bool | None = None
|
|
90
|
+
#: Phonetic algorithm to use for this field.
|
|
91
|
+
phonetic: StringT | None = None
|
|
92
|
+
#: Weight of this field in the document's ranking. The default is 1.0.
|
|
93
|
+
weight: int | float | None = None
|
|
94
|
+
#: Separator to use for splitting tags if the field is of
|
|
95
|
+
#: type :attr:`~coredis.PureToken.TAG`.
|
|
96
|
+
separator: StringT | None = None
|
|
97
|
+
#: For fields of type :attr:`~coredis.PureToken.TAG`,
|
|
98
|
+
#: keeps the original letter cases of the tags. If not specified,
|
|
99
|
+
#: the characters are converted to lowercase.
|
|
100
|
+
casesensitive: bool | None = None
|
|
101
|
+
#: For fields of type :attr:`~coredis.PureToken.TAG` &
|
|
102
|
+
#: :attr:`~coredis.PureToken.TEXT`, keeps a suffix trie with all
|
|
103
|
+
#: terms which match the suffix. It is used to optimize contains ``(foo)``
|
|
104
|
+
#: and suffix ``(*foo)`` queries. Otherwise, a brute-force search on the trie
|
|
105
|
+
#: is performed. If suffix trie exists for some fields, these queries will
|
|
106
|
+
#: be disabled for other fields
|
|
107
|
+
withsuffixtrie: bool | None = None
|
|
108
|
+
#: The algorithm to use for indexing if the field is of type
|
|
109
|
+
#: :attr:`~coredis.PureToken.VECTOR`.
|
|
110
|
+
#: For more details refer to the
|
|
111
|
+
#: `Vector similarity <https://redis.io/docs/stack/search/reference/vectors/>`__
|
|
112
|
+
#: section of the RediSearch documentation.
|
|
113
|
+
algorithm: Literal["FLAT", "HSNW"] | None = None
|
|
114
|
+
#: A dictionary of attributes to be used with the :paramref:`algorithm` specified.
|
|
115
|
+
#: For more details refer to the
|
|
116
|
+
#: `Creation attributes per algorithm <https://redis.io/docs/stack/search/reference/vectors/#creation-attributes-per-algorithm>`__
|
|
117
|
+
#: section of the RediSearch documentation.
|
|
118
|
+
attributes: dict[StringT, ValueT] | None = None
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def args(self) -> tuple[ValueT, ...]:
|
|
122
|
+
args: CommandArgList = [self.name]
|
|
123
|
+
if self.alias:
|
|
124
|
+
args += [PrefixToken.AS, self.alias]
|
|
125
|
+
args += [self.type]
|
|
126
|
+
if self.type == PureToken.VECTOR:
|
|
127
|
+
assert self.algorithm
|
|
128
|
+
|
|
129
|
+
args += [self.algorithm]
|
|
130
|
+
if self.attributes:
|
|
131
|
+
_attributes: list[ValueT] = list(itertools.chain(*self.attributes.items()))
|
|
132
|
+
args += [len(_attributes)]
|
|
133
|
+
args += _attributes
|
|
134
|
+
|
|
135
|
+
if self.sortable:
|
|
136
|
+
args += [PureToken.SORTABLE]
|
|
137
|
+
if self.unf:
|
|
138
|
+
args += [PureToken.UNF]
|
|
139
|
+
if self.nostem:
|
|
140
|
+
args += [b"NOSTEM"]
|
|
141
|
+
if self.noindex:
|
|
142
|
+
args += [PureToken.NOINDEX]
|
|
143
|
+
if self.phonetic:
|
|
144
|
+
args += [b"PHONETIC", self.phonetic]
|
|
145
|
+
if self.weight:
|
|
146
|
+
args += [b"WEIGHT", self.weight]
|
|
147
|
+
if self.separator:
|
|
148
|
+
args += [PrefixToken.SEPARATOR, self.separator]
|
|
149
|
+
if self.casesensitive:
|
|
150
|
+
args += [b"CASESENSITIVE"]
|
|
151
|
+
if self.withsuffixtrie:
|
|
152
|
+
args += [PureToken.WITHSUFFIXTRIE]
|
|
153
|
+
return tuple(args)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@dataclasses.dataclass
|
|
157
|
+
class Reduce:
|
|
158
|
+
"""
|
|
159
|
+
Reduce definition to be used with :paramref:`~coredis.modules.Search.aggregate.transformations`
|
|
160
|
+
to define ``REDUCE`` steps in :meth:`~coredis.modules.Search.aggregate`
|
|
161
|
+
|
|
162
|
+
For more details refer to `GroupBy Reducers <https://redis.io/docs/stack/search/reference/aggregations/#groupby-reducers>`__
|
|
163
|
+
in the RediSearch documentation.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
#: The name of the reducer function
|
|
167
|
+
function: StringT
|
|
168
|
+
#: The arguments to the reducer function
|
|
169
|
+
parameters: Parameters[ValueT] | None = None
|
|
170
|
+
#: The alias to assign to the result of the reducer function
|
|
171
|
+
alias: StringT | None = None
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def args(self) -> CommandArgList:
|
|
175
|
+
args: CommandArgList = [self.function]
|
|
176
|
+
if self.parameters:
|
|
177
|
+
args.extend(self.parameters)
|
|
178
|
+
if self.alias:
|
|
179
|
+
args.extend([PrefixToken.AS, self.alias])
|
|
180
|
+
return args
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@dataclasses.dataclass
|
|
184
|
+
class Group:
|
|
185
|
+
"""
|
|
186
|
+
Group definition to be used with :paramref:`~coredis.modules.Search.aggregate.transformations`
|
|
187
|
+
to specify ``GROUPBY`` steps in :meth:`~coredis.modules.Search.aggregate`
|
|
188
|
+
|
|
189
|
+
For more details refer to
|
|
190
|
+
`Aggregations <https://redis.io/docs/stack/search/reference/aggregations>`__
|
|
191
|
+
in the RediSearch documentation.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
#: The field to group by
|
|
195
|
+
by: StringT | Parameters[StringT]
|
|
196
|
+
#: The reducers to apply to each group
|
|
197
|
+
reducers: Parameters[Reduce] | None = None
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def args(self) -> CommandArgList:
|
|
201
|
+
args: CommandArgList = [PrefixToken.GROUPBY]
|
|
202
|
+
if isinstance(self.by, (bytes, str)):
|
|
203
|
+
args.extend([1, self.by])
|
|
204
|
+
else:
|
|
205
|
+
bies: list[StringT] = list(self.by)
|
|
206
|
+
args.extend([len(bies), *bies])
|
|
207
|
+
for reducer in self.reducers or []:
|
|
208
|
+
args.append(PureToken.REDUCE)
|
|
209
|
+
args.extend(reducer.args)
|
|
210
|
+
|
|
211
|
+
return args
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@dataclasses.dataclass
|
|
215
|
+
class Apply:
|
|
216
|
+
"""
|
|
217
|
+
Apply definition to be used with :paramref:`~coredis.modules.Search.aggregate.transformations`
|
|
218
|
+
to specify ``APPLY`` steps in :meth:`~coredis.modules.Search.aggregate`
|
|
219
|
+
|
|
220
|
+
For more details refer to
|
|
221
|
+
`APPLY expressions <https://redis.io/docs/stack/search/reference/aggregations/#apply-expressions>`__
|
|
222
|
+
in the RediSearch documentation.
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
#: The expression to apply
|
|
226
|
+
function: StringT
|
|
227
|
+
#: The alias to assign to the result of the expression
|
|
228
|
+
alias: StringT
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def args(self) -> CommandArgList:
|
|
232
|
+
return [PrefixToken.APPLY, self.function, PrefixToken.AS, self.alias]
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@dataclasses.dataclass
|
|
236
|
+
class Filter:
|
|
237
|
+
"""
|
|
238
|
+
Filter definition to be used with :paramref:`~coredis.modules.Search.aggregate.transformations`
|
|
239
|
+
to specify ``FILTER`` steps in :meth:`~coredis.modules.Search.aggregate`
|
|
240
|
+
|
|
241
|
+
For more details refer to
|
|
242
|
+
`FILTER expressions <https://redis.io/docs/stack/search/reference/aggregations/#filter-expressions>`__
|
|
243
|
+
in the RediSearch documentation.
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
#: The filter expression
|
|
247
|
+
expression: StringT
|
|
248
|
+
|
|
249
|
+
@property
|
|
250
|
+
def args(self) -> CommandArgList:
|
|
251
|
+
return [PrefixToken.FILTER, self.expression]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@versionadded(version="4.12")
|
|
255
|
+
class Search(ModuleGroup[AnyStr]):
|
|
256
|
+
MODULE = RediSearch
|
|
257
|
+
COMMAND_GROUP = CommandGroup.SEARCH
|
|
258
|
+
|
|
259
|
+
@module_command(
|
|
260
|
+
CommandName.FT_CREATE,
|
|
261
|
+
module=MODULE,
|
|
262
|
+
version_introduced="1.0.0",
|
|
263
|
+
group=COMMAND_GROUP,
|
|
264
|
+
)
|
|
265
|
+
def create(
|
|
266
|
+
self,
|
|
267
|
+
index: KeyT,
|
|
268
|
+
schema: Parameters[Field],
|
|
269
|
+
*,
|
|
270
|
+
on: Literal[PureToken.HASH, PureToken.JSON] | None = None,
|
|
271
|
+
prefixes: Parameters[StringT] | None = None,
|
|
272
|
+
filter_expression: StringT | None = None,
|
|
273
|
+
language: StringT | None = None,
|
|
274
|
+
language_field: StringT | None = None,
|
|
275
|
+
score: int | float | None = None,
|
|
276
|
+
score_field: StringT | None = None,
|
|
277
|
+
payload_field: StringT | None = None,
|
|
278
|
+
maxtextfields: bool | None = None,
|
|
279
|
+
temporary: int | timedelta | None = None,
|
|
280
|
+
nooffsets: bool | None = None,
|
|
281
|
+
nohl: bool | None = None,
|
|
282
|
+
nofields: bool | None = None,
|
|
283
|
+
nofreqs: bool | None = None,
|
|
284
|
+
stopwords: Parameters[StringT] | None = None,
|
|
285
|
+
skipinitialscan: bool | None = None,
|
|
286
|
+
) -> CommandRequest[bool]:
|
|
287
|
+
"""
|
|
288
|
+
Creates an index with the given spec
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
:param index: The name of the index to create.
|
|
292
|
+
:param schema: A list of schema fields
|
|
293
|
+
:param on: The type of Redis key to index.
|
|
294
|
+
:param prefixes: A list of key prefixes to index.
|
|
295
|
+
:param filter_expression: A filter expression to apply to the index.
|
|
296
|
+
:param language: The default language to use for text fields.
|
|
297
|
+
:param language_field: The name of the field to use for language detection.
|
|
298
|
+
:param score: The default score to use for documents.
|
|
299
|
+
:param score_field: The name of the field to use for document scoring.
|
|
300
|
+
:param payload_field: The name of the field to use for document payloads.
|
|
301
|
+
:param maxtextfields: If ``True``, the maximum number of text fields will be used.
|
|
302
|
+
:param temporary: If specified, the index will be temporary and
|
|
303
|
+
will expire after the given number of seconds.
|
|
304
|
+
:param nooffsets: If ``True``, term offsets will not be stored.
|
|
305
|
+
:param nohl: If ``True``, search results will not include highlighted snippets.
|
|
306
|
+
:param nofields: If ``True``, search results will not include field values.
|
|
307
|
+
:param nofreqs: If ``True``, term frequencies will not be stored.
|
|
308
|
+
:param stopwords: A list of stopwords to ignore.
|
|
309
|
+
:param skipinitialscan: If ``True``, the initial scan of the index will be skipped.
|
|
310
|
+
"""
|
|
311
|
+
command_arguments: CommandArgList = [index]
|
|
312
|
+
if on:
|
|
313
|
+
command_arguments.extend([PrefixToken.ON, on])
|
|
314
|
+
|
|
315
|
+
if prefixes:
|
|
316
|
+
_prefixes: list[StringT] = list(prefixes)
|
|
317
|
+
command_arguments.extend([PrefixToken.PREFIX, len(_prefixes), *_prefixes])
|
|
318
|
+
if filter_expression:
|
|
319
|
+
command_arguments.extend([PrefixToken.FILTER, filter_expression])
|
|
320
|
+
if language:
|
|
321
|
+
command_arguments.extend([PrefixToken.LANGUAGE, language])
|
|
322
|
+
if language_field:
|
|
323
|
+
command_arguments.extend([PrefixToken.LANGUAGE_FIELD, language_field])
|
|
324
|
+
if score:
|
|
325
|
+
command_arguments.extend([PrefixToken.SCORE, score])
|
|
326
|
+
if score_field:
|
|
327
|
+
command_arguments.extend([PrefixToken.SCORE_FIELD, score_field])
|
|
328
|
+
if payload_field:
|
|
329
|
+
command_arguments.extend([PrefixToken.PAYLOAD_FIELD, payload_field])
|
|
330
|
+
if maxtextfields:
|
|
331
|
+
command_arguments.append(PureToken.MAXTEXTFIELDS)
|
|
332
|
+
if temporary:
|
|
333
|
+
command_arguments.extend([PrefixToken.TEMPORARY, normalized_seconds(temporary)])
|
|
334
|
+
if nooffsets:
|
|
335
|
+
command_arguments.append(PureToken.NOOFFSETS)
|
|
336
|
+
if nohl:
|
|
337
|
+
command_arguments.append(PureToken.NOHL)
|
|
338
|
+
if nofields:
|
|
339
|
+
command_arguments.append(PureToken.NOFIELDS)
|
|
340
|
+
if nofreqs:
|
|
341
|
+
command_arguments.append(PureToken.NOFREQS)
|
|
342
|
+
if stopwords:
|
|
343
|
+
_stop: list[StringT] = list(stopwords)
|
|
344
|
+
command_arguments.extend([PrefixToken.STOPWORDS, len(_stop), *_stop])
|
|
345
|
+
if skipinitialscan:
|
|
346
|
+
command_arguments.append(PureToken.SKIPINITIALSCAN)
|
|
347
|
+
|
|
348
|
+
field_args: CommandArgList = [PureToken.SCHEMA]
|
|
349
|
+
for field in schema:
|
|
350
|
+
field_args.extend(field.args)
|
|
351
|
+
command_arguments.extend(field_args)
|
|
352
|
+
|
|
353
|
+
return self.client.create_request(
|
|
354
|
+
CommandName.FT_CREATE, *command_arguments, callback=SimpleStringCallback()
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
@module_command(
|
|
358
|
+
CommandName.FT_INFO,
|
|
359
|
+
module=MODULE,
|
|
360
|
+
version_introduced="1.0.0",
|
|
361
|
+
group=COMMAND_GROUP,
|
|
362
|
+
)
|
|
363
|
+
def info(self, index: KeyT) -> CommandRequest[dict[AnyStr, ResponseType]]:
|
|
364
|
+
"""
|
|
365
|
+
Returns information and statistics on the index
|
|
366
|
+
|
|
367
|
+
:param index: The name of the index.
|
|
368
|
+
"""
|
|
369
|
+
return self.client.create_request(
|
|
370
|
+
CommandName.FT_INFO,
|
|
371
|
+
index,
|
|
372
|
+
callback=DictCallback[AnyStr, ResponseType](
|
|
373
|
+
recursive=[
|
|
374
|
+
"attributes",
|
|
375
|
+
"index_definition",
|
|
376
|
+
"gc_stats",
|
|
377
|
+
"cursor_stats",
|
|
378
|
+
"dialect_stats",
|
|
379
|
+
]
|
|
380
|
+
),
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
@module_command(
|
|
384
|
+
CommandName.FT_EXPLAIN,
|
|
385
|
+
module=MODULE,
|
|
386
|
+
version_introduced="1.0.0",
|
|
387
|
+
group=COMMAND_GROUP,
|
|
388
|
+
arguments={"dialect": {"version_introduced": "2.4.3"}},
|
|
389
|
+
)
|
|
390
|
+
def explain(
|
|
391
|
+
self, index: KeyT, query: StringT, dialect: int | None = None
|
|
392
|
+
) -> CommandRequest[AnyStr]:
|
|
393
|
+
"""
|
|
394
|
+
Returns the execution plan for a complex query
|
|
395
|
+
|
|
396
|
+
:param index: The name of the index to query.
|
|
397
|
+
:param query: The query to explain.
|
|
398
|
+
:param dialect: Query dialect to use.
|
|
399
|
+
"""
|
|
400
|
+
command_arguments: CommandArgList = [index, query]
|
|
401
|
+
if dialect:
|
|
402
|
+
command_arguments.extend([PrefixToken.DIALECT, dialect])
|
|
403
|
+
return self.client.create_request(
|
|
404
|
+
CommandName.FT_EXPLAIN,
|
|
405
|
+
*command_arguments,
|
|
406
|
+
callback=AnyStrCallback[AnyStr](),
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
@module_command(
|
|
410
|
+
CommandName.FT_ALTER,
|
|
411
|
+
module=MODULE,
|
|
412
|
+
version_introduced="1.0.0",
|
|
413
|
+
group=COMMAND_GROUP,
|
|
414
|
+
)
|
|
415
|
+
def alter(
|
|
416
|
+
self,
|
|
417
|
+
index: KeyT,
|
|
418
|
+
field: Field,
|
|
419
|
+
skipinitialscan: bool | None = None,
|
|
420
|
+
) -> CommandRequest[bool]:
|
|
421
|
+
"""
|
|
422
|
+
Adds a new field to the index
|
|
423
|
+
|
|
424
|
+
:param index: The name of the index to alter.
|
|
425
|
+
:param field: The new field to add
|
|
426
|
+
:param skipinitialscan: If ``True``, skip the initial scan and indexing.
|
|
427
|
+
|
|
428
|
+
"""
|
|
429
|
+
command_arguments: CommandArgList = [index]
|
|
430
|
+
if skipinitialscan:
|
|
431
|
+
command_arguments.append(PureToken.SKIPINITIALSCAN)
|
|
432
|
+
command_arguments.extend([PureToken.SCHEMA, PureToken.ADD, *field.args])
|
|
433
|
+
|
|
434
|
+
return self.client.create_request(
|
|
435
|
+
CommandName.FT_ALTER, *command_arguments, callback=SimpleStringCallback()
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
@module_command(
|
|
439
|
+
CommandName.FT_DROPINDEX,
|
|
440
|
+
module=MODULE,
|
|
441
|
+
version_introduced="2.0.0",
|
|
442
|
+
group=COMMAND_GROUP,
|
|
443
|
+
)
|
|
444
|
+
def dropindex(self, index: KeyT, delete_docs: bool | None = None) -> CommandRequest[bool]:
|
|
445
|
+
"""
|
|
446
|
+
Deletes the index
|
|
447
|
+
|
|
448
|
+
:param index: The name of the index to delete.
|
|
449
|
+
:param delete_docs: If ``True``, delete the documents associated with the index.
|
|
450
|
+
"""
|
|
451
|
+
command_arguments: CommandArgList = [index]
|
|
452
|
+
if delete_docs:
|
|
453
|
+
command_arguments.append(PureToken.DELETE_DOCS)
|
|
454
|
+
|
|
455
|
+
return self.client.create_request(
|
|
456
|
+
CommandName.FT_DROPINDEX,
|
|
457
|
+
*command_arguments,
|
|
458
|
+
callback=SimpleStringCallback(),
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
@module_command(
|
|
462
|
+
CommandName.FT_ALIASADD,
|
|
463
|
+
module=MODULE,
|
|
464
|
+
version_introduced="1.0.0",
|
|
465
|
+
group=COMMAND_GROUP,
|
|
466
|
+
)
|
|
467
|
+
def aliasadd(self, alias: StringT, index: KeyT) -> CommandRequest[bool]:
|
|
468
|
+
"""
|
|
469
|
+
Adds an alias to the index
|
|
470
|
+
|
|
471
|
+
:param alias: The alias to be added to the index.
|
|
472
|
+
:param index: The index to which the alias will be added.
|
|
473
|
+
"""
|
|
474
|
+
|
|
475
|
+
return self.client.create_request(
|
|
476
|
+
CommandName.FT_ALIASADD, alias, index, callback=SimpleStringCallback()
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
@module_command(
|
|
480
|
+
CommandName.FT_ALIASUPDATE,
|
|
481
|
+
module=MODULE,
|
|
482
|
+
version_introduced="1.0.0",
|
|
483
|
+
group=COMMAND_GROUP,
|
|
484
|
+
)
|
|
485
|
+
def aliasupdate(self, alias: StringT, index: KeyT) -> CommandRequest[bool]:
|
|
486
|
+
"""
|
|
487
|
+
Adds or updates an alias to the index
|
|
488
|
+
|
|
489
|
+
:param alias: The alias to be added to an index.
|
|
490
|
+
:param index: The index to which the alias will be added.
|
|
491
|
+
"""
|
|
492
|
+
|
|
493
|
+
return self.client.create_request(
|
|
494
|
+
CommandName.FT_ALIASUPDATE, alias, index, callback=SimpleStringCallback()
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
@module_command(
|
|
498
|
+
CommandName.FT_ALIASDEL,
|
|
499
|
+
module=MODULE,
|
|
500
|
+
version_introduced="1.0.0",
|
|
501
|
+
group=COMMAND_GROUP,
|
|
502
|
+
)
|
|
503
|
+
def aliasdel(self, alias: StringT) -> CommandRequest[bool]:
|
|
504
|
+
"""
|
|
505
|
+
Deletes an alias from the index
|
|
506
|
+
|
|
507
|
+
:param alias: The index alias to be removed.
|
|
508
|
+
"""
|
|
509
|
+
|
|
510
|
+
return self.client.create_request(
|
|
511
|
+
CommandName.FT_ALIASDEL, alias, callback=SimpleStringCallback()
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
@module_command(
|
|
515
|
+
CommandName.FT_TAGVALS,
|
|
516
|
+
module=MODULE,
|
|
517
|
+
version_introduced="1.0.0",
|
|
518
|
+
group=COMMAND_GROUP,
|
|
519
|
+
)
|
|
520
|
+
def tagvals(self, index: KeyT, field_name: StringT) -> CommandRequest[set[AnyStr]]:
|
|
521
|
+
"""
|
|
522
|
+
Returns the distinct tags indexed in a Tag field
|
|
523
|
+
|
|
524
|
+
:param index: The name of the index.
|
|
525
|
+
:param field_name: Name of a Tag field defined in the schema.
|
|
526
|
+
"""
|
|
527
|
+
|
|
528
|
+
return self.client.create_request(
|
|
529
|
+
CommandName.FT_TAGVALS, index, field_name, callback=SetCallback[AnyStr]()
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
@module_command(
|
|
533
|
+
CommandName.FT_SYNUPDATE,
|
|
534
|
+
module=MODULE,
|
|
535
|
+
version_introduced="1.2.0",
|
|
536
|
+
group=COMMAND_GROUP,
|
|
537
|
+
)
|
|
538
|
+
def synupdate(
|
|
539
|
+
self,
|
|
540
|
+
index: KeyT,
|
|
541
|
+
synonym_group: StringT,
|
|
542
|
+
terms: Parameters[StringT],
|
|
543
|
+
skipinitialscan: bool | None = None,
|
|
544
|
+
) -> CommandRequest[bool]:
|
|
545
|
+
"""
|
|
546
|
+
Creates or updates a synonym group with additional terms
|
|
547
|
+
|
|
548
|
+
:param index: The name of the index.
|
|
549
|
+
:param synonym_group: The ID of the synonym group to update.
|
|
550
|
+
:param terms: A list of terms to add to the synonym group.
|
|
551
|
+
:param skipinitialscan: If ``True``, only documents indexed after the
|
|
552
|
+
update will be affected.
|
|
553
|
+
|
|
554
|
+
"""
|
|
555
|
+
command_arguments: CommandArgList = [index, synonym_group]
|
|
556
|
+
if skipinitialscan:
|
|
557
|
+
command_arguments.append(PureToken.SKIPINITIALSCAN)
|
|
558
|
+
command_arguments.extend(terms)
|
|
559
|
+
return self.client.create_request(
|
|
560
|
+
CommandName.FT_SYNUPDATE,
|
|
561
|
+
*command_arguments,
|
|
562
|
+
callback=SimpleStringCallback(),
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
@module_command(
|
|
566
|
+
CommandName.FT_SYNDUMP,
|
|
567
|
+
module=MODULE,
|
|
568
|
+
version_introduced="1.2.0",
|
|
569
|
+
group=COMMAND_GROUP,
|
|
570
|
+
)
|
|
571
|
+
def syndump(self, index: KeyT) -> CommandRequest[dict[AnyStr, list[AnyStr]]]:
|
|
572
|
+
"""
|
|
573
|
+
Dumps the contents of a synonym group
|
|
574
|
+
|
|
575
|
+
:param index: The name of the index.
|
|
576
|
+
"""
|
|
577
|
+
|
|
578
|
+
return self.client.create_request(
|
|
579
|
+
CommandName.FT_SYNDUMP,
|
|
580
|
+
index,
|
|
581
|
+
callback=DictCallback[AnyStr, list[AnyStr]](),
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
@module_command(
|
|
585
|
+
CommandName.FT_SPELLCHECK,
|
|
586
|
+
module=MODULE,
|
|
587
|
+
version_introduced="1.4.0",
|
|
588
|
+
group=COMMAND_GROUP,
|
|
589
|
+
arguments={"dialect": {"version_introduced": "2.4.3"}},
|
|
590
|
+
)
|
|
591
|
+
def spellcheck(
|
|
592
|
+
self,
|
|
593
|
+
index: KeyT,
|
|
594
|
+
query: StringT,
|
|
595
|
+
distance: int | None = None,
|
|
596
|
+
include: StringT | None = None,
|
|
597
|
+
exclude: StringT | None = None,
|
|
598
|
+
dialect: int | None = None,
|
|
599
|
+
) -> CommandRequest[dict[AnyStr, OrderedDict[AnyStr, float]]]:
|
|
600
|
+
"""
|
|
601
|
+
Performs spelling correction on a query, returning suggestions for misspelled terms
|
|
602
|
+
|
|
603
|
+
:param index: The name of the index with the indexed terms.
|
|
604
|
+
:param query: The search query.
|
|
605
|
+
:param distance: Maximum Levenshtein distance for spelling suggestions
|
|
606
|
+
:param include: Specifies an inclusion of a custom dictionary
|
|
607
|
+
:param exclude: Specifies an exclusion of a custom dictionary
|
|
608
|
+
:param dialect: The query dialect to use.
|
|
609
|
+
"""
|
|
610
|
+
command_arguments: CommandArgList = [index, query]
|
|
611
|
+
if distance:
|
|
612
|
+
command_arguments.extend([PrefixToken.DISTANCE, distance])
|
|
613
|
+
if exclude:
|
|
614
|
+
command_arguments.extend([PrefixToken.TERMS, PureToken.EXCLUDE, exclude])
|
|
615
|
+
if include:
|
|
616
|
+
command_arguments.extend([PrefixToken.TERMS, PureToken.INCLUDE, include])
|
|
617
|
+
if dialect:
|
|
618
|
+
command_arguments.extend([PrefixToken.DIALECT, dialect])
|
|
619
|
+
return self.client.create_request(
|
|
620
|
+
CommandName.FT_SPELLCHECK,
|
|
621
|
+
*command_arguments,
|
|
622
|
+
callback=SpellCheckCallback[AnyStr](),
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
@module_command(
|
|
626
|
+
CommandName.FT_DICTADD,
|
|
627
|
+
module=MODULE,
|
|
628
|
+
version_introduced="1.4.0",
|
|
629
|
+
group=COMMAND_GROUP,
|
|
630
|
+
)
|
|
631
|
+
def dictadd(
|
|
632
|
+
self,
|
|
633
|
+
name: StringT,
|
|
634
|
+
terms: Parameters[StringT],
|
|
635
|
+
) -> CommandRequest[int]:
|
|
636
|
+
"""
|
|
637
|
+
Adds terms to a dictionary
|
|
638
|
+
|
|
639
|
+
:param name: The name of the dictionary.
|
|
640
|
+
:param terms: The terms to add to the dictionary.
|
|
641
|
+
"""
|
|
642
|
+
command_arguments: CommandArgList = [name, *terms]
|
|
643
|
+
|
|
644
|
+
return self.client.create_request(
|
|
645
|
+
CommandName.FT_DICTADD, *command_arguments, callback=IntCallback()
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
@module_command(
|
|
649
|
+
CommandName.FT_DICTDEL,
|
|
650
|
+
module=MODULE,
|
|
651
|
+
version_introduced="1.4.0",
|
|
652
|
+
group=COMMAND_GROUP,
|
|
653
|
+
)
|
|
654
|
+
def dictdel(
|
|
655
|
+
self,
|
|
656
|
+
name: StringT,
|
|
657
|
+
terms: Parameters[StringT],
|
|
658
|
+
) -> CommandRequest[int]:
|
|
659
|
+
"""
|
|
660
|
+
Deletes terms from a dictionary
|
|
661
|
+
|
|
662
|
+
:param name: The name of the dictionary.
|
|
663
|
+
:param terms: The terms to delete from the dictionary.
|
|
664
|
+
"""
|
|
665
|
+
command_arguments: CommandArgList = [name, *terms]
|
|
666
|
+
|
|
667
|
+
return self.client.create_request(
|
|
668
|
+
CommandName.FT_DICTDEL, *command_arguments, callback=IntCallback()
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
@module_command(
|
|
672
|
+
CommandName.FT_DICTDUMP,
|
|
673
|
+
module=MODULE,
|
|
674
|
+
version_introduced="1.4.0",
|
|
675
|
+
group=COMMAND_GROUP,
|
|
676
|
+
)
|
|
677
|
+
def dictdump(self, name: StringT) -> CommandRequest[set[AnyStr]]:
|
|
678
|
+
"""
|
|
679
|
+
Dumps all terms in the given dictionary
|
|
680
|
+
|
|
681
|
+
:param name: The name of the dictionary to dump.
|
|
682
|
+
"""
|
|
683
|
+
|
|
684
|
+
return self.client.create_request(
|
|
685
|
+
CommandName.FT_DICTDUMP, name, callback=SetCallback[AnyStr]()
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
@module_command(
|
|
689
|
+
CommandName.FT__LIST,
|
|
690
|
+
module=MODULE,
|
|
691
|
+
version_introduced="2.0.0",
|
|
692
|
+
group=COMMAND_GROUP,
|
|
693
|
+
cluster=ClusterCommandConfig(
|
|
694
|
+
route=NodeFlag.PRIMARIES,
|
|
695
|
+
combine=ClusterMergeSets[AnyStr](),
|
|
696
|
+
),
|
|
697
|
+
)
|
|
698
|
+
def list(self) -> CommandRequest[set[AnyStr]]:
|
|
699
|
+
"""
|
|
700
|
+
Returns a list of all existing indexes
|
|
701
|
+
"""
|
|
702
|
+
return self.client.create_request(CommandName.FT__LIST, callback=SetCallback[AnyStr]())
|
|
703
|
+
|
|
704
|
+
@module_command(
|
|
705
|
+
CommandName.FT_CONFIG_SET,
|
|
706
|
+
module=MODULE,
|
|
707
|
+
version_introduced="1.0.0",
|
|
708
|
+
version_deprecated="8.0.0",
|
|
709
|
+
group=COMMAND_GROUP,
|
|
710
|
+
cluster=ClusterCommandConfig(
|
|
711
|
+
route=NodeFlag.PRIMARIES,
|
|
712
|
+
combine=ClusterEnsureConsistent[bool](),
|
|
713
|
+
),
|
|
714
|
+
)
|
|
715
|
+
def config_set(self, option: StringT, value: ValueT) -> CommandRequest[bool]:
|
|
716
|
+
"""
|
|
717
|
+
Sets runtime configuration options
|
|
718
|
+
"""
|
|
719
|
+
|
|
720
|
+
return self.client.create_request(
|
|
721
|
+
CommandName.FT_CONFIG_SET, option, value, callback=SimpleStringCallback()
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
@module_command(
|
|
725
|
+
CommandName.FT_CONFIG_GET,
|
|
726
|
+
module=MODULE,
|
|
727
|
+
version_introduced="1.0.0",
|
|
728
|
+
version_deprecated="8.0.0",
|
|
729
|
+
group=COMMAND_GROUP,
|
|
730
|
+
cluster=ClusterCommandConfig(
|
|
731
|
+
route=NodeFlag.RANDOM,
|
|
732
|
+
),
|
|
733
|
+
)
|
|
734
|
+
def config_get(self, option: StringT) -> CommandRequest[dict[AnyStr, ResponsePrimitive]]:
|
|
735
|
+
"""
|
|
736
|
+
Retrieves runtime configuration options
|
|
737
|
+
"""
|
|
738
|
+
|
|
739
|
+
return self.client.create_request(
|
|
740
|
+
CommandName.FT_CONFIG_GET,
|
|
741
|
+
option,
|
|
742
|
+
callback=SearchConfigCallback[AnyStr](),
|
|
743
|
+
)
|
|
744
|
+
|
|
745
|
+
@module_command(
|
|
746
|
+
CommandName.FT_SEARCH,
|
|
747
|
+
module=MODULE,
|
|
748
|
+
version_introduced="1.0.0",
|
|
749
|
+
group=COMMAND_GROUP,
|
|
750
|
+
arguments={"dialect": {"version_introduced": "2.4.3"}},
|
|
751
|
+
)
|
|
752
|
+
def search(
|
|
753
|
+
self,
|
|
754
|
+
index: KeyT,
|
|
755
|
+
query: StringT,
|
|
756
|
+
*,
|
|
757
|
+
nocontent: bool | None = None,
|
|
758
|
+
verbatim: bool | None = None,
|
|
759
|
+
nostopwords: bool | None = None,
|
|
760
|
+
withscores: bool | None = None,
|
|
761
|
+
withpayloads: bool | None = None,
|
|
762
|
+
withsortkeys: bool | None = None,
|
|
763
|
+
numeric_filters: None
|
|
764
|
+
| (Mapping[StringT, tuple[int | float | StringT, int | float | StringT]]) = None,
|
|
765
|
+
geo_filters: None
|
|
766
|
+
| (
|
|
767
|
+
Mapping[
|
|
768
|
+
StringT,
|
|
769
|
+
tuple[
|
|
770
|
+
tuple[int | float, int | float],
|
|
771
|
+
int | float,
|
|
772
|
+
Literal[PureToken.KM, PureToken.M, PureToken.MI, PureToken.FT],
|
|
773
|
+
],
|
|
774
|
+
]
|
|
775
|
+
) = None,
|
|
776
|
+
in_keys: Parameters[StringT] | None = None,
|
|
777
|
+
in_fields: Parameters[StringT] | None = None,
|
|
778
|
+
returns: Mapping[StringT, StringT | None] | None = None,
|
|
779
|
+
summarize_fields: Parameters[StringT] | None = None,
|
|
780
|
+
summarize_frags: int | None = None,
|
|
781
|
+
summarize_length: int | None = None,
|
|
782
|
+
summarize_separator: StringT | None = None,
|
|
783
|
+
highlight_fields: Parameters[StringT] | None = None,
|
|
784
|
+
highlight_tags: tuple[StringT, StringT] | None = None,
|
|
785
|
+
slop: int | None = None,
|
|
786
|
+
timeout: int | timedelta | None = None,
|
|
787
|
+
inorder: bool | None = None,
|
|
788
|
+
language: StringT | None = None,
|
|
789
|
+
expander: StringT | None = None,
|
|
790
|
+
scorer: StringT | None = None,
|
|
791
|
+
explainscore: bool | None = None,
|
|
792
|
+
payload: StringT | None = None,
|
|
793
|
+
sortby: StringT | None = None,
|
|
794
|
+
sort_order: Literal[PureToken.ASC, PureToken.DESC] | None = None,
|
|
795
|
+
offset: int | None = 0,
|
|
796
|
+
limit: int | None = None,
|
|
797
|
+
parameters: Mapping[StringT, ValueT] | None = None,
|
|
798
|
+
dialect: int | None = None,
|
|
799
|
+
) -> CommandRequest[SearchResult[AnyStr]]:
|
|
800
|
+
"""
|
|
801
|
+
Searches the index with a textual query, returning either documents or just ids
|
|
802
|
+
|
|
803
|
+
:param index: The name of the index to search.
|
|
804
|
+
:param query: The text query to search.
|
|
805
|
+
:param nocontent: If ``True``, returns the document ids and not the content.
|
|
806
|
+
:param verbatim: If ``True``, does not try to use stemming for query expansion
|
|
807
|
+
but searches the query terms verbatim.
|
|
808
|
+
:param nostopwords: If ``True``, disables stopword filtering.
|
|
809
|
+
:param withscores: If ``True``, also returns the relative internal score of each document.
|
|
810
|
+
:param withpayloads: If ``True``, retrieves optional document payloads.
|
|
811
|
+
:param withsortkeys: If ``True``, returns the value of the sorting key
|
|
812
|
+
:param numeric_filters: A dictionary of numeric filters.
|
|
813
|
+
Limits results to those having numeric values ranging between min and max,
|
|
814
|
+
:param geo_filters: A dictionary of geo filters.
|
|
815
|
+
Filters the results to a given radius from lon and lat.
|
|
816
|
+
Radius is given as a number and units.
|
|
817
|
+
:param in_keys: A list of keys to limit the result to.
|
|
818
|
+
Non-existent keys are ignored, unless all the keys are non-existent.
|
|
819
|
+
:param in_fields: Filters the results to those appearing only in specific
|
|
820
|
+
attributes of the document, like title or URL.
|
|
821
|
+
:param returns: A dictionary of attributes to return from the document. The values
|
|
822
|
+
in the dictionary are used as an alias for the attribute name and if ``None``,
|
|
823
|
+
the attribute will be returned as is.
|
|
824
|
+
:param summarize_fields: A list of fields to summarize. If not ``None``,
|
|
825
|
+
returns a summary of the fields.
|
|
826
|
+
:param summarize_frags: The number of fragments to return in the summary.
|
|
827
|
+
:param summarize_length: The length of each fragment in the summary.
|
|
828
|
+
:param summarize_separator: The separator to use between fragments in the summary.
|
|
829
|
+
:param highlight_fields: A list of fields to highlight.
|
|
830
|
+
:param highlight_tags: A tuple of opening and closing tags to use for highlighting.
|
|
831
|
+
:param slop: The number of words allowed between query terms.
|
|
832
|
+
:param timeout: The timeout for the search query.
|
|
833
|
+
:param inorder: If ``True``, requires that the query terms appear in the same order
|
|
834
|
+
as in the query.
|
|
835
|
+
:param language: The language to use for stemming.
|
|
836
|
+
:param expander: The query expander to use.
|
|
837
|
+
:param scorer: The scorer to use.
|
|
838
|
+
:param explainscore: If ``True``, returns an explanation of the score.
|
|
839
|
+
:param payload: The payload to return.
|
|
840
|
+
:param sortby: The field to sort by.
|
|
841
|
+
:param sort_order: The order to sort by.
|
|
842
|
+
:param offset: The offset to start returning results from.
|
|
843
|
+
:param limit: The maximum number of results to return.
|
|
844
|
+
:param parameters: A dictionary of parameters to pass to the query.
|
|
845
|
+
:param dialect: The query dialect to use.
|
|
846
|
+
|
|
847
|
+
"""
|
|
848
|
+
command_arguments: CommandArgList = [index, query]
|
|
849
|
+
if nocontent:
|
|
850
|
+
command_arguments.append(PureToken.NOCONTENT)
|
|
851
|
+
if verbatim:
|
|
852
|
+
command_arguments.append(PureToken.VERBATIM)
|
|
853
|
+
if nostopwords:
|
|
854
|
+
command_arguments.append(PureToken.NOSTOPWORDS)
|
|
855
|
+
if withscores:
|
|
856
|
+
command_arguments.append(PureToken.WITHSCORES)
|
|
857
|
+
if withpayloads:
|
|
858
|
+
command_arguments.append(PureToken.WITHPAYLOADS)
|
|
859
|
+
if withsortkeys:
|
|
860
|
+
command_arguments.append(PureToken.WITHSORTKEYS)
|
|
861
|
+
if numeric_filters:
|
|
862
|
+
for field, numeric_filter in numeric_filters.items():
|
|
863
|
+
command_arguments.extend(
|
|
864
|
+
[PrefixToken.FILTER, field, numeric_filter[0], numeric_filter[1]]
|
|
865
|
+
)
|
|
866
|
+
if geo_filters:
|
|
867
|
+
for field, gfilter in geo_filters.items():
|
|
868
|
+
command_arguments.extend(
|
|
869
|
+
[
|
|
870
|
+
PrefixToken.GEOFILTER,
|
|
871
|
+
field,
|
|
872
|
+
gfilter[0][0],
|
|
873
|
+
gfilter[0][1],
|
|
874
|
+
gfilter[1],
|
|
875
|
+
gfilter[2],
|
|
876
|
+
]
|
|
877
|
+
)
|
|
878
|
+
if in_keys:
|
|
879
|
+
_in_keys: list[StringT] = list(in_keys)
|
|
880
|
+
command_arguments.extend([PrefixToken.INKEYS, len(_in_keys), *_in_keys])
|
|
881
|
+
if in_fields:
|
|
882
|
+
_in_fields: list[StringT] = list(in_fields)
|
|
883
|
+
command_arguments.extend([PrefixToken.INFIELDS, len(_in_fields), *_in_fields])
|
|
884
|
+
if returns:
|
|
885
|
+
return_items: CommandArgList = []
|
|
886
|
+
for identifier, property in returns.items():
|
|
887
|
+
return_items.append(identifier)
|
|
888
|
+
if property:
|
|
889
|
+
return_items.extend([PrefixToken.AS, property])
|
|
890
|
+
command_arguments.extend([PrefixToken.RETURN, len(return_items), *return_items])
|
|
891
|
+
if sortby:
|
|
892
|
+
command_arguments.extend([PrefixToken.SORTBY, sortby])
|
|
893
|
+
if sort_order:
|
|
894
|
+
command_arguments.append(sort_order)
|
|
895
|
+
if summarize_fields or summarize_frags or summarize_length or summarize_separator:
|
|
896
|
+
command_arguments.append(PureToken.SUMMARIZE)
|
|
897
|
+
if summarize_fields:
|
|
898
|
+
_fields: list[StringT] = list(summarize_fields)
|
|
899
|
+
command_arguments.extend([PrefixToken.FIELDS, len(_fields), *_fields])
|
|
900
|
+
if summarize_frags:
|
|
901
|
+
command_arguments.extend([PrefixToken.FRAGS, summarize_frags])
|
|
902
|
+
if summarize_length:
|
|
903
|
+
command_arguments.extend([PrefixToken.LEN, summarize_length])
|
|
904
|
+
if summarize_separator:
|
|
905
|
+
command_arguments.extend([PrefixToken.SEPARATOR, summarize_separator])
|
|
906
|
+
if highlight_fields or highlight_tags:
|
|
907
|
+
command_arguments.append(PureToken.HIGHLIGHT)
|
|
908
|
+
if highlight_fields:
|
|
909
|
+
_fields = list(highlight_fields)
|
|
910
|
+
command_arguments.extend([PrefixToken.FIELDS, len(_fields), *_fields])
|
|
911
|
+
if highlight_tags:
|
|
912
|
+
command_arguments.extend([PureToken.TAGS, highlight_tags[0], highlight_tags[1]])
|
|
913
|
+
if slop is not None:
|
|
914
|
+
command_arguments.extend([PrefixToken.SLOP, slop])
|
|
915
|
+
if timeout:
|
|
916
|
+
command_arguments.extend([PrefixToken.TIMEOUT, normalized_milliseconds(timeout)])
|
|
917
|
+
if inorder:
|
|
918
|
+
command_arguments.append(PureToken.INORDER)
|
|
919
|
+
if language:
|
|
920
|
+
command_arguments.extend([PrefixToken.LANGUAGE, language])
|
|
921
|
+
if expander: # noqa
|
|
922
|
+
command_arguments.extend([PrefixToken.EXPANDER, expander])
|
|
923
|
+
if scorer: # noqa
|
|
924
|
+
command_arguments.extend([PrefixToken.SCORER, scorer])
|
|
925
|
+
if explainscore:
|
|
926
|
+
command_arguments.append(PureToken.EXPLAINSCORE)
|
|
927
|
+
if payload:
|
|
928
|
+
command_arguments.extend([PrefixToken.PAYLOAD, payload])
|
|
929
|
+
if limit is not None:
|
|
930
|
+
command_arguments.extend([PrefixToken.LIMIT, offset or 0, limit])
|
|
931
|
+
if parameters:
|
|
932
|
+
_parameters: list[ValueT] = list(itertools.chain(*parameters.items()))
|
|
933
|
+
command_arguments.extend([PureToken.PARAMS, len(_parameters), *_parameters])
|
|
934
|
+
if dialect:
|
|
935
|
+
command_arguments.extend([PrefixToken.DIALECT, dialect])
|
|
936
|
+
|
|
937
|
+
return self.client.create_request(
|
|
938
|
+
CommandName.FT_SEARCH,
|
|
939
|
+
*command_arguments,
|
|
940
|
+
callback=SearchResultCallback[AnyStr](
|
|
941
|
+
withscores=withscores,
|
|
942
|
+
withpayloads=withpayloads,
|
|
943
|
+
withsortkeys=withsortkeys,
|
|
944
|
+
explainscore=explainscore,
|
|
945
|
+
nocontent=nocontent,
|
|
946
|
+
),
|
|
947
|
+
)
|
|
948
|
+
|
|
949
|
+
@module_command(
|
|
950
|
+
CommandName.FT_AGGREGATE,
|
|
951
|
+
module=MODULE,
|
|
952
|
+
version_introduced="1.1.0",
|
|
953
|
+
group=COMMAND_GROUP,
|
|
954
|
+
arguments={"dialect": {"version_introduced": "2.4.3"}},
|
|
955
|
+
)
|
|
956
|
+
def aggregate(
|
|
957
|
+
self,
|
|
958
|
+
index: KeyT,
|
|
959
|
+
query: StringT,
|
|
960
|
+
*,
|
|
961
|
+
verbatim: bool | None = None,
|
|
962
|
+
load: None | (Literal["*"] | Parameters[StringT | tuple[StringT, StringT]]) = None,
|
|
963
|
+
timeout: int | timedelta | None = None,
|
|
964
|
+
transforms: Parameters[Group | Apply | Filter] | None = None,
|
|
965
|
+
sortby: Mapping[StringT, Literal[PureToken.ASC, PureToken.DESC]] | None = None,
|
|
966
|
+
sortby_max: int | None = None,
|
|
967
|
+
offset: int | None = 0,
|
|
968
|
+
limit: int | None = None,
|
|
969
|
+
with_cursor: bool | None = None,
|
|
970
|
+
cursor_read_size: int | None = None,
|
|
971
|
+
cursor_maxidle: int | timedelta | None = None,
|
|
972
|
+
parameters: Mapping[StringT, StringT] | None = None,
|
|
973
|
+
dialect: int | None = None,
|
|
974
|
+
) -> CommandRequest[SearchAggregationResult[AnyStr]]:
|
|
975
|
+
"""
|
|
976
|
+
Perform aggregate transformations on search results from a Redis index.
|
|
977
|
+
|
|
978
|
+
:param index: Name of the Redis index to search.
|
|
979
|
+
:param query: Base filtering query to retrieve documents.
|
|
980
|
+
:param verbatim: If ``True``, search query terms verbatim.
|
|
981
|
+
:param load: Load document attributes from the source document.
|
|
982
|
+
:param timeout: Maximum time to wait for the query to complete.
|
|
983
|
+
:param transforms: List of transformations to apply to the results.
|
|
984
|
+
:param sortby: Sort the pipeline up to the point of SORTBY.
|
|
985
|
+
:param sortby_max: Optimize sorting by sorting only for the n-largest elements.
|
|
986
|
+
:param offset: Number of results to skip.
|
|
987
|
+
:param limit: Maximum number of results to return.
|
|
988
|
+
:param with_cursor: If ``True``, return a cursor for large result sets.
|
|
989
|
+
:param cursor_read_size: Number of results to read from the cursor at a time.
|
|
990
|
+
:param cursor_maxidle: Maximum idle time for the cursor.
|
|
991
|
+
:param parameters: Additional parameters to pass to the query.
|
|
992
|
+
:param dialect: Query dialect to use.
|
|
993
|
+
|
|
994
|
+
:return: Aggregated search results from the Redis index.
|
|
995
|
+
|
|
996
|
+
"""
|
|
997
|
+
command_arguments: CommandArgList = [index, query]
|
|
998
|
+
if verbatim:
|
|
999
|
+
command_arguments.append(PureToken.VERBATIM)
|
|
1000
|
+
if timeout:
|
|
1001
|
+
command_arguments.extend([PrefixToken.TIMEOUT, normalized_milliseconds(timeout)])
|
|
1002
|
+
if load:
|
|
1003
|
+
command_arguments.append(PrefixToken.LOAD)
|
|
1004
|
+
if isinstance(load, (bytes, str)):
|
|
1005
|
+
command_arguments.append(load)
|
|
1006
|
+
else:
|
|
1007
|
+
_load_fields: list[StringT] = []
|
|
1008
|
+
for field in load:
|
|
1009
|
+
if isinstance(field, (bytes, str)):
|
|
1010
|
+
_load_fields.append(field)
|
|
1011
|
+
else:
|
|
1012
|
+
_load_fields.extend([field[0], PrefixToken.AS, field[1]])
|
|
1013
|
+
|
|
1014
|
+
command_arguments.extend([len(_load_fields), *_load_fields])
|
|
1015
|
+
|
|
1016
|
+
if transforms:
|
|
1017
|
+
for step in transforms:
|
|
1018
|
+
command_arguments.extend(step.args)
|
|
1019
|
+
|
|
1020
|
+
if sortby:
|
|
1021
|
+
command_arguments.append(PrefixToken.SORTBY)
|
|
1022
|
+
command_arguments.append(len(sortby) * 2)
|
|
1023
|
+
for field, order in sortby.items():
|
|
1024
|
+
command_arguments.extend([field, order])
|
|
1025
|
+
if sortby_max:
|
|
1026
|
+
command_arguments.extend([PrefixToken.MAX, sortby_max])
|
|
1027
|
+
|
|
1028
|
+
if limit is not None:
|
|
1029
|
+
command_arguments.extend([PrefixToken.LIMIT, offset or 0, limit])
|
|
1030
|
+
|
|
1031
|
+
if with_cursor:
|
|
1032
|
+
command_arguments.append(PureToken.WITHCURSOR)
|
|
1033
|
+
if cursor_read_size:
|
|
1034
|
+
command_arguments.extend([PrefixToken.COUNT, cursor_read_size])
|
|
1035
|
+
if cursor_maxidle:
|
|
1036
|
+
command_arguments.extend(
|
|
1037
|
+
[PrefixToken.MAXIDLE, normalized_milliseconds(cursor_maxidle)]
|
|
1038
|
+
)
|
|
1039
|
+
if parameters:
|
|
1040
|
+
_parameters: list[StringT] = list(itertools.chain(*parameters.items()))
|
|
1041
|
+
command_arguments.extend([PureToken.PARAMS, len(_parameters), *_parameters])
|
|
1042
|
+
if dialect:
|
|
1043
|
+
command_arguments.extend([PrefixToken.DIALECT, dialect])
|
|
1044
|
+
return self.client.create_request(
|
|
1045
|
+
CommandName.FT_AGGREGATE,
|
|
1046
|
+
*command_arguments,
|
|
1047
|
+
callback=AggregationResultCallback[AnyStr](with_cursor=with_cursor, dialect=dialect),
|
|
1048
|
+
)
|
|
1049
|
+
|
|
1050
|
+
@module_command(
|
|
1051
|
+
CommandName.FT_CURSOR_READ,
|
|
1052
|
+
module=MODULE,
|
|
1053
|
+
version_introduced="1.1.0",
|
|
1054
|
+
group=COMMAND_GROUP,
|
|
1055
|
+
)
|
|
1056
|
+
def cursor_read(
|
|
1057
|
+
self, index: KeyT, cursor_id: int, count: int | None = None
|
|
1058
|
+
) -> CommandRequest[SearchAggregationResult[AnyStr]]:
|
|
1059
|
+
"""
|
|
1060
|
+
Reads from a cursor
|
|
1061
|
+
"""
|
|
1062
|
+
command_arguments: CommandArgList = [index, cursor_id]
|
|
1063
|
+
if count:
|
|
1064
|
+
command_arguments.extend([PrefixToken.COUNT, count])
|
|
1065
|
+
|
|
1066
|
+
return self.client.create_request(
|
|
1067
|
+
CommandName.FT_CURSOR_READ,
|
|
1068
|
+
*command_arguments,
|
|
1069
|
+
callback=AggregationResultCallback[AnyStr](with_cursor=True),
|
|
1070
|
+
)
|
|
1071
|
+
|
|
1072
|
+
@module_command(
|
|
1073
|
+
CommandName.FT_CURSOR_DEL,
|
|
1074
|
+
module=MODULE,
|
|
1075
|
+
version_introduced="1.1.0",
|
|
1076
|
+
group=COMMAND_GROUP,
|
|
1077
|
+
)
|
|
1078
|
+
def cursor_del(self, index: KeyT, cursor_id: int) -> CommandRequest[bool]:
|
|
1079
|
+
"""
|
|
1080
|
+
Deletes a cursor
|
|
1081
|
+
|
|
1082
|
+
"""
|
|
1083
|
+
command_arguments: CommandArgList = [index, cursor_id]
|
|
1084
|
+
|
|
1085
|
+
return self.client.create_request(
|
|
1086
|
+
CommandName.FT_CURSOR_DEL,
|
|
1087
|
+
*command_arguments,
|
|
1088
|
+
callback=SimpleStringCallback(),
|
|
1089
|
+
)
|