We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add dialect support for RediSearch queries

**Version**: What redis-py and what redis version is the issue happening on?
RediSearch>=2.4.3 

On RediSearch 2.4.3 we will introduce a new `DIALECT` command argument for queries (`FT.SEARCH`, `FT.AGGREGATE`) this will allow to process queries either by the current dialect (RediSearch 2.2.x) or the new dialect introduced on RediSearch 2.4.2.
New dialect features:
1. parameterized queries 
2. VSS
3. Improved syntax behavior as introduced at https://github.com/RediSearch/RediSearch/releases/tag/v2.4.2

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `redis/commands/search/query.py`
Content:
```
1 class Query:
2     """
3     Query is used to build complex queries that have more parameters than just
4     the query string. The query string is set in the constructor, and other
5     options have setter functions.
6 
7     The setter functions return the query object, so they can be chained,
8     i.e. `Query("foo").verbatim().filter(...)` etc.
9     """
10 
11     def __init__(self, query_string):
12         """
13         Create a new query object.
14         The query string is set in the constructor, and other options have
15         setter functions.
16         """
17 
18         self._query_string = query_string
19         self._offset = 0
20         self._num = 10
21         self._no_content = False
22         self._no_stopwords = False
23         self._fields = None
24         self._verbatim = False
25         self._with_payloads = False
26         self._with_scores = False
27         self._scorer = False
28         self._filters = list()
29         self._ids = None
30         self._slop = -1
31         self._in_order = False
32         self._sortby = None
33         self._return_fields = []
34         self._summarize_fields = []
35         self._highlight_fields = []
36         self._language = None
37         self._expander = None
38 
39     def query_string(self):
40         """Return the query string of this query only."""
41         return self._query_string
42 
43     def limit_ids(self, *ids):
44         """Limit the results to a specific set of pre-known document
45         ids of any length."""
46         self._ids = ids
47         return self
48 
49     def return_fields(self, *fields):
50         """Add fields to return fields."""
51         self._return_fields += fields
52         return self
53 
54     def return_field(self, field, as_field=None):
55         """Add field to return fields (Optional: add 'AS' name
56         to the field)."""
57         self._return_fields.append(field)
58         if as_field is not None:
59             self._return_fields += ("AS", as_field)
60         return self
61 
62     def _mk_field_list(self, fields):
63         if not fields:
64             return []
65         return [fields] if isinstance(fields, str) else list(fields)
66 
67     def summarize(self, fields=None, context_len=None, num_frags=None, sep=None):
68         """
69         Return an abridged format of the field, containing only the segments of
70         the field which contain the matching term(s).
71 
72         If `fields` is specified, then only the mentioned fields are
73         summarized; otherwise all results are summarized.
74 
75         Server side defaults are used for each option (except `fields`)
76         if not specified
77 
78         - **fields** List of fields to summarize. All fields are summarized
79         if not specified
80         - **context_len** Amount of context to include with each fragment
81         - **num_frags** Number of fragments per document
82         - **sep** Separator string to separate fragments
83         """
84         args = ["SUMMARIZE"]
85         fields = self._mk_field_list(fields)
86         if fields:
87             args += ["FIELDS", str(len(fields))] + fields
88 
89         if context_len is not None:
90             args += ["LEN", str(context_len)]
91         if num_frags is not None:
92             args += ["FRAGS", str(num_frags)]
93         if sep is not None:
94             args += ["SEPARATOR", sep]
95 
96         self._summarize_fields = args
97         return self
98 
99     def highlight(self, fields=None, tags=None):
100         """
101         Apply specified markup to matched term(s) within the returned field(s).
102 
103         - **fields** If specified then only those mentioned fields are
104         highlighted, otherwise all fields are highlighted
105         - **tags** A list of two strings to surround the match.
106         """
107         args = ["HIGHLIGHT"]
108         fields = self._mk_field_list(fields)
109         if fields:
110             args += ["FIELDS", str(len(fields))] + fields
111         if tags:
112             args += ["TAGS"] + list(tags)
113 
114         self._highlight_fields = args
115         return self
116 
117     def language(self, language):
118         """
119         Analyze the query as being in the specified language.
120 
121         :param language: The language (e.g. `chinese` or `english`)
122         """
123         self._language = language
124         return self
125 
126     def slop(self, slop):
127         """Allow a maximum of N intervening non matched terms between
128         phrase terms (0 means exact phrase).
129         """
130         self._slop = slop
131         return self
132 
133     def in_order(self):
134         """
135         Match only documents where the query terms appear in
136         the same order in the document.
137         i.e. for the query "hello world", we do not match "world hello"
138         """
139         self._in_order = True
140         return self
141 
142     def scorer(self, scorer):
143         """
144         Use a different scoring function to evaluate document relevance.
145         Default is `TFIDF`.
146 
147         :param scorer: The scoring function to use
148                        (e.g. `TFIDF.DOCNORM` or `BM25`)
149         """
150         self._scorer = scorer
151         return self
152 
153     def get_args(self):
154         """Format the redis arguments for this query and return them."""
155         args = [self._query_string]
156         args += self._get_args_tags()
157         args += self._summarize_fields + self._highlight_fields
158         args += ["LIMIT", self._offset, self._num]
159         return args
160 
161     def _get_args_tags(self):
162         args = []
163         if self._no_content:
164             args.append("NOCONTENT")
165         if self._fields:
166             args.append("INFIELDS")
167             args.append(len(self._fields))
168             args += self._fields
169         if self._verbatim:
170             args.append("VERBATIM")
171         if self._no_stopwords:
172             args.append("NOSTOPWORDS")
173         if self._filters:
174             for flt in self._filters:
175                 if not isinstance(flt, Filter):
176                     raise AttributeError("Did not receive a Filter object.")
177                 args += flt.args
178         if self._with_payloads:
179             args.append("WITHPAYLOADS")
180         if self._scorer:
181             args += ["SCORER", self._scorer]
182         if self._with_scores:
183             args.append("WITHSCORES")
184         if self._ids:
185             args.append("INKEYS")
186             args.append(len(self._ids))
187             args += self._ids
188         if self._slop >= 0:
189             args += ["SLOP", self._slop]
190         if self._in_order:
191             args.append("INORDER")
192         if self._return_fields:
193             args.append("RETURN")
194             args.append(len(self._return_fields))
195             args += self._return_fields
196         if self._sortby:
197             if not isinstance(self._sortby, SortbyField):
198                 raise AttributeError("Did not receive a SortByField.")
199             args.append("SORTBY")
200             args += self._sortby.args
201         if self._language:
202             args += ["LANGUAGE", self._language]
203         if self._expander:
204             args += ["EXPANDER", self._expander]
205 
206         return args
207 
208     def paging(self, offset, num):
209         """
210         Set the paging for the query (defaults to 0..10).
211 
212         - **offset**: Paging offset for the results. Defaults to 0
213         - **num**: How many results do we want
214         """
215         self._offset = offset
216         self._num = num
217         return self
218 
219     def verbatim(self):
220         """Set the query to be verbatim, i.e. use no query expansion
221         or stemming.
222         """
223         self._verbatim = True
224         return self
225 
226     def no_content(self):
227         """Set the query to only return ids and not the document content."""
228         self._no_content = True
229         return self
230 
231     def no_stopwords(self):
232         """
233         Prevent the query from being filtered for stopwords.
234         Only useful in very big queries that you are certain contain
235         no stopwords.
236         """
237         self._no_stopwords = True
238         return self
239 
240     def with_payloads(self):
241         """Ask the engine to return document payloads."""
242         self._with_payloads = True
243         return self
244 
245     def with_scores(self):
246         """Ask the engine to return document search scores."""
247         self._with_scores = True
248         return self
249 
250     def limit_fields(self, *fields):
251         """
252         Limit the search to specific TEXT fields only.
253 
254         - **fields**: A list of strings, case sensitive field names
255         from the defined schema.
256         """
257         self._fields = fields
258         return self
259 
260     def add_filter(self, flt):
261         """
262         Add a numeric or geo filter to the query.
263         **Currently only one of each filter is supported by the engine**
264 
265         - **flt**: A NumericFilter or GeoFilter object, used on a
266         corresponding field
267         """
268 
269         self._filters.append(flt)
270         return self
271 
272     def sort_by(self, field, asc=True):
273         """
274         Add a sortby field to the query.
275 
276         - **field** - the name of the field to sort by
277         - **asc** - when `True`, sorting will be done in asceding order
278         """
279         self._sortby = SortbyField(field, asc)
280         return self
281 
282     def expander(self, expander):
283         """
284         Add a expander field to the query.
285 
286         - **expander** - the name of the expander
287         """
288         self._expander = expander
289         return self
290 
291 
292 class Filter:
293     def __init__(self, keyword, field, *args):
294         self.args = [keyword, field] + list(args)
295 
296 
297 class NumericFilter(Filter):
298     INF = "+inf"
299     NEG_INF = "-inf"
300 
301     def __init__(self, field, minval, maxval, minExclusive=False, maxExclusive=False):
302         args = [
303             minval if not minExclusive else f"({minval}",
304             maxval if not maxExclusive else f"({maxval}",
305         ]
306 
307         Filter.__init__(self, "FILTER", field, *args)
308 
309 
310 class GeoFilter(Filter):
311     METERS = "m"
312     KILOMETERS = "km"
313     FEET = "ft"
314     MILES = "mi"
315 
316     def __init__(self, field, lon, lat, radius, unit=KILOMETERS):
317         Filter.__init__(self, "GEOFILTER", field, lon, lat, radius, unit)
318 
319 
320 class SortbyField:
321     def __init__(self, field, asc=True):
322         self.args = [field, "ASC" if asc else "DESC"]
323
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/redis/commands/search/query.py b/redis/commands/search/query.py
--- a/redis/commands/search/query.py
+++ b/redis/commands/search/query.py
@@ -35,6 +35,7 @@
         self._highlight_fields = []
         self._language = None
         self._expander = None
+        self._dialect = None
 
     def query_string(self):
         """Return the query string of this query only."""
@@ -202,6 +203,8 @@
             args += ["LANGUAGE", self._language]
         if self._expander:
             args += ["EXPANDER", self._expander]
+        if self._dialect:
+            args += ["DIALECT", self._dialect]
 
         return args
 
@@ -288,6 +291,15 @@
         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):

{"golden_diff": "diff --git a/redis/commands/search/query.py b/redis/commands/search/query.py\n--- a/redis/commands/search/query.py\n+++ b/redis/commands/search/query.py\n@@ -35,6 +35,7 @@\n         self._highlight_fields = []\n         self._language = None\n         self._expander = None\n+        self._dialect = None\n \n     def query_string(self):\n         \"\"\"Return the query string of this query only.\"\"\"\n@@ -202,6 +203,8 @@\n             args += [\"LANGUAGE\", self._language]\n         if self._expander:\n             args += [\"EXPANDER\", self._expander]\n+        if self._dialect:\n+            args += [\"DIALECT\", self._dialect]\n \n         return args\n \n@@ -288,6 +291,15 @@\n         self._expander = expander\n         return self\n \n+    def dialect(self, dialect: int) -> \"Query\":\n+        \"\"\"\n+        Add a dialect field to the query.\n+\n+        - **dialect** - dialect version to execute the query under\n+        \"\"\"\n+        self._dialect = dialect\n+        return self\n+\n \n class Filter:\n     def __init__(self, keyword, field, *args):\n", "issue": "Add dialect support for RediSearch queries\n\r\n**Version**: What redis-py and what redis version is the issue happening on?\r\nRediSearch>=2.4.3 \r\n\r\nOn RediSearch 2.4.3 we will introduce a new `DIALECT` command argument for queries (`FT.SEARCH`, `FT.AGGREGATE`) this will allow to process queries either by the current dialect (RediSearch 2.2.x) or the new dialect introduced on RediSearch 2.4.2.\r\nNew dialect features:\r\n1. parameterized queries \r\n2. VSS\r\n3. Improved syntax behavior as introduced at https://github.com/RediSearch/RediSearch/releases/tag/v2.4.2\n", "before_files": [{"content": "class Query:\n    \"\"\"\n    Query is used to build complex queries that have more parameters than just\n    the query string. The query string is set in the constructor, and other\n    options have setter functions.\n\n    The setter functions return the query object, so they can be chained,\n    i.e. `Query(\"foo\").verbatim().filter(...)` etc.\n    \"\"\"\n\n    def __init__(self, query_string):\n        \"\"\"\n        Create a new query object.\n        The query string is set in the constructor, and other options have\n        setter functions.\n        \"\"\"\n\n        self._query_string = query_string\n        self._offset = 0\n        self._num = 10\n        self._no_content = False\n        self._no_stopwords = False\n        self._fields = None\n        self._verbatim = False\n        self._with_payloads = False\n        self._with_scores = False\n        self._scorer = False\n        self._filters = list()\n        self._ids = None\n        self._slop = -1\n        self._in_order = False\n        self._sortby = None\n        self._return_fields = []\n        self._summarize_fields = []\n        self._highlight_fields = []\n        self._language = None\n        self._expander = None\n\n    def query_string(self):\n        \"\"\"Return the query string of this query only.\"\"\"\n        return self._query_string\n\n    def limit_ids(self, *ids):\n        \"\"\"Limit the results to a specific set of pre-known document\n        ids of any length.\"\"\"\n        self._ids = ids\n        return self\n\n    def return_fields(self, *fields):\n        \"\"\"Add fields to return fields.\"\"\"\n        self._return_fields += fields\n        return self\n\n    def return_field(self, field, as_field=None):\n        \"\"\"Add field to return fields (Optional: add 'AS' name\n        to the field).\"\"\"\n        self._return_fields.append(field)\n        if as_field is not None:\n            self._return_fields += (\"AS\", as_field)\n        return self\n\n    def _mk_field_list(self, fields):\n        if not fields:\n            return []\n        return [fields] if isinstance(fields, str) else list(fields)\n\n    def summarize(self, fields=None, context_len=None, num_frags=None, sep=None):\n        \"\"\"\n        Return an abridged format of the field, containing only the segments of\n        the field which contain the matching term(s).\n\n        If `fields` is specified, then only the mentioned fields are\n        summarized; otherwise all results are summarized.\n\n        Server side defaults are used for each option (except `fields`)\n        if not specified\n\n        - **fields** List of fields to summarize. All fields are summarized\n        if not specified\n        - **context_len** Amount of context to include with each fragment\n        - **num_frags** Number of fragments per document\n        - **sep** Separator string to separate fragments\n        \"\"\"\n        args = [\"SUMMARIZE\"]\n        fields = self._mk_field_list(fields)\n        if fields:\n            args += [\"FIELDS\", str(len(fields))] + fields\n\n        if context_len is not None:\n            args += [\"LEN\", str(context_len)]\n        if num_frags is not None:\n            args += [\"FRAGS\", str(num_frags)]\n        if sep is not None:\n            args += [\"SEPARATOR\", sep]\n\n        self._summarize_fields = args\n        return self\n\n    def highlight(self, fields=None, tags=None):\n        \"\"\"\n        Apply specified markup to matched term(s) within the returned field(s).\n\n        - **fields** If specified then only those mentioned fields are\n        highlighted, otherwise all fields are highlighted\n        - **tags** A list of two strings to surround the match.\n        \"\"\"\n        args = [\"HIGHLIGHT\"]\n        fields = self._mk_field_list(fields)\n        if fields:\n            args += [\"FIELDS\", str(len(fields))] + fields\n        if tags:\n            args += [\"TAGS\"] + list(tags)\n\n        self._highlight_fields = args\n        return self\n\n    def language(self, language):\n        \"\"\"\n        Analyze the query as being in the specified language.\n\n        :param language: The language (e.g. `chinese` or `english`)\n        \"\"\"\n        self._language = language\n        return self\n\n    def slop(self, slop):\n        \"\"\"Allow a maximum of N intervening non matched terms between\n        phrase terms (0 means exact phrase).\n        \"\"\"\n        self._slop = slop\n        return self\n\n    def in_order(self):\n        \"\"\"\n        Match only documents where the query terms appear in\n        the same order in the document.\n        i.e. for the query \"hello world\", we do not match \"world hello\"\n        \"\"\"\n        self._in_order = True\n        return self\n\n    def scorer(self, scorer):\n        \"\"\"\n        Use a different scoring function to evaluate document relevance.\n        Default is `TFIDF`.\n\n        :param scorer: The scoring function to use\n                       (e.g. `TFIDF.DOCNORM` or `BM25`)\n        \"\"\"\n        self._scorer = scorer\n        return self\n\n    def get_args(self):\n        \"\"\"Format the redis arguments for this query and return them.\"\"\"\n        args = [self._query_string]\n        args += self._get_args_tags()\n        args += self._summarize_fields + self._highlight_fields\n        args += [\"LIMIT\", self._offset, self._num]\n        return args\n\n    def _get_args_tags(self):\n        args = []\n        if self._no_content:\n            args.append(\"NOCONTENT\")\n        if self._fields:\n            args.append(\"INFIELDS\")\n            args.append(len(self._fields))\n            args += self._fields\n        if self._verbatim:\n            args.append(\"VERBATIM\")\n        if self._no_stopwords:\n            args.append(\"NOSTOPWORDS\")\n        if self._filters:\n            for flt in self._filters:\n                if not isinstance(flt, Filter):\n                    raise AttributeError(\"Did not receive a Filter object.\")\n                args += flt.args\n        if self._with_payloads:\n            args.append(\"WITHPAYLOADS\")\n        if self._scorer:\n            args += [\"SCORER\", self._scorer]\n        if self._with_scores:\n            args.append(\"WITHSCORES\")\n        if self._ids:\n            args.append(\"INKEYS\")\n            args.append(len(self._ids))\n            args += self._ids\n        if self._slop >= 0:\n            args += [\"SLOP\", self._slop]\n        if self._in_order:\n            args.append(\"INORDER\")\n        if self._return_fields:\n            args.append(\"RETURN\")\n            args.append(len(self._return_fields))\n            args += self._return_fields\n        if self._sortby:\n            if not isinstance(self._sortby, SortbyField):\n                raise AttributeError(\"Did not receive a SortByField.\")\n            args.append(\"SORTBY\")\n            args += self._sortby.args\n        if self._language:\n            args += [\"LANGUAGE\", self._language]\n        if self._expander:\n            args += [\"EXPANDER\", self._expander]\n\n        return args\n\n    def paging(self, offset, num):\n        \"\"\"\n        Set the paging for the query (defaults to 0..10).\n\n        - **offset**: Paging offset for the results. Defaults to 0\n        - **num**: How many results do we want\n        \"\"\"\n        self._offset = offset\n        self._num = num\n        return self\n\n    def verbatim(self):\n        \"\"\"Set the query to be verbatim, i.e. use no query expansion\n        or stemming.\n        \"\"\"\n        self._verbatim = True\n        return self\n\n    def no_content(self):\n        \"\"\"Set the query to only return ids and not the document content.\"\"\"\n        self._no_content = True\n        return self\n\n    def no_stopwords(self):\n        \"\"\"\n        Prevent the query from being filtered for stopwords.\n        Only useful in very big queries that you are certain contain\n        no stopwords.\n        \"\"\"\n        self._no_stopwords = True\n        return self\n\n    def with_payloads(self):\n        \"\"\"Ask the engine to return document payloads.\"\"\"\n        self._with_payloads = True\n        return self\n\n    def with_scores(self):\n        \"\"\"Ask the engine to return document search scores.\"\"\"\n        self._with_scores = True\n        return self\n\n    def limit_fields(self, *fields):\n        \"\"\"\n        Limit the search to specific TEXT fields only.\n\n        - **fields**: A list of strings, case sensitive field names\n        from the defined schema.\n        \"\"\"\n        self._fields = fields\n        return self\n\n    def add_filter(self, flt):\n        \"\"\"\n        Add a numeric or geo filter to the query.\n        **Currently only one of each filter is supported by the engine**\n\n        - **flt**: A NumericFilter or GeoFilter object, used on a\n        corresponding field\n        \"\"\"\n\n        self._filters.append(flt)\n        return self\n\n    def sort_by(self, field, asc=True):\n        \"\"\"\n        Add a sortby field to the query.\n\n        - **field** - the name of the field to sort by\n        - **asc** - when `True`, sorting will be done in asceding order\n        \"\"\"\n        self._sortby = SortbyField(field, asc)\n        return self\n\n    def expander(self, expander):\n        \"\"\"\n        Add a expander field to the query.\n\n        - **expander** - the name of the expander\n        \"\"\"\n        self._expander = expander\n        return self\n\n\nclass Filter:\n    def __init__(self, keyword, field, *args):\n        self.args = [keyword, field] + list(args)\n\n\nclass NumericFilter(Filter):\n    INF = \"+inf\"\n    NEG_INF = \"-inf\"\n\n    def __init__(self, field, minval, maxval, minExclusive=False, maxExclusive=False):\n        args = [\n            minval if not minExclusive else f\"({minval}\",\n            maxval if not maxExclusive else f\"({maxval}\",\n        ]\n\n        Filter.__init__(self, \"FILTER\", field, *args)\n\n\nclass GeoFilter(Filter):\n    METERS = \"m\"\n    KILOMETERS = \"km\"\n    FEET = \"ft\"\n    MILES = \"mi\"\n\n    def __init__(self, field, lon, lat, radius, unit=KILOMETERS):\n        Filter.__init__(self, \"GEOFILTER\", field, lon, lat, radius, unit)\n\n\nclass SortbyField:\n    def __init__(self, field, asc=True):\n        self.args = [field, \"ASC\" if asc else \"DESC\"]\n", "path": "redis/commands/search/query.py"}], "after_files": [{"content": "class Query:\n    \"\"\"\n    Query is used to build complex queries that have more parameters than just\n    the query string. The query string is set in the constructor, and other\n    options have setter functions.\n\n    The setter functions return the query object, so they can be chained,\n    i.e. `Query(\"foo\").verbatim().filter(...)` etc.\n    \"\"\"\n\n    def __init__(self, query_string):\n        \"\"\"\n        Create a new query object.\n        The query string is set in the constructor, and other options have\n        setter functions.\n        \"\"\"\n\n        self._query_string = query_string\n        self._offset = 0\n        self._num = 10\n        self._no_content = False\n        self._no_stopwords = False\n        self._fields = None\n        self._verbatim = False\n        self._with_payloads = False\n        self._with_scores = False\n        self._scorer = False\n        self._filters = list()\n        self._ids = None\n        self._slop = -1\n        self._in_order = False\n        self._sortby = None\n        self._return_fields = []\n        self._summarize_fields = []\n        self._highlight_fields = []\n        self._language = None\n        self._expander = None\n        self._dialect = None\n\n    def query_string(self):\n        \"\"\"Return the query string of this query only.\"\"\"\n        return self._query_string\n\n    def limit_ids(self, *ids):\n        \"\"\"Limit the results to a specific set of pre-known document\n        ids of any length.\"\"\"\n        self._ids = ids\n        return self\n\n    def return_fields(self, *fields):\n        \"\"\"Add fields to return fields.\"\"\"\n        self._return_fields += fields\n        return self\n\n    def return_field(self, field, as_field=None):\n        \"\"\"Add field to return fields (Optional: add 'AS' name\n        to the field).\"\"\"\n        self._return_fields.append(field)\n        if as_field is not None:\n            self._return_fields += (\"AS\", as_field)\n        return self\n\n    def _mk_field_list(self, fields):\n        if not fields:\n            return []\n        return [fields] if isinstance(fields, str) else list(fields)\n\n    def summarize(self, fields=None, context_len=None, num_frags=None, sep=None):\n        \"\"\"\n        Return an abridged format of the field, containing only the segments of\n        the field which contain the matching term(s).\n\n        If `fields` is specified, then only the mentioned fields are\n        summarized; otherwise all results are summarized.\n\n        Server side defaults are used for each option (except `fields`)\n        if not specified\n\n        - **fields** List of fields to summarize. All fields are summarized\n        if not specified\n        - **context_len** Amount of context to include with each fragment\n        - **num_frags** Number of fragments per document\n        - **sep** Separator string to separate fragments\n        \"\"\"\n        args = [\"SUMMARIZE\"]\n        fields = self._mk_field_list(fields)\n        if fields:\n            args += [\"FIELDS\", str(len(fields))] + fields\n\n        if context_len is not None:\n            args += [\"LEN\", str(context_len)]\n        if num_frags is not None:\n            args += [\"FRAGS\", str(num_frags)]\n        if sep is not None:\n            args += [\"SEPARATOR\", sep]\n\n        self._summarize_fields = args\n        return self\n\n    def highlight(self, fields=None, tags=None):\n        \"\"\"\n        Apply specified markup to matched term(s) within the returned field(s).\n\n        - **fields** If specified then only those mentioned fields are\n        highlighted, otherwise all fields are highlighted\n        - **tags** A list of two strings to surround the match.\n        \"\"\"\n        args = [\"HIGHLIGHT\"]\n        fields = self._mk_field_list(fields)\n        if fields:\n            args += [\"FIELDS\", str(len(fields))] + fields\n        if tags:\n            args += [\"TAGS\"] + list(tags)\n\n        self._highlight_fields = args\n        return self\n\n    def language(self, language):\n        \"\"\"\n        Analyze the query as being in the specified language.\n\n        :param language: The language (e.g. `chinese` or `english`)\n        \"\"\"\n        self._language = language\n        return self\n\n    def slop(self, slop):\n        \"\"\"Allow a maximum of N intervening non matched terms between\n        phrase terms (0 means exact phrase).\n        \"\"\"\n        self._slop = slop\n        return self\n\n    def in_order(self):\n        \"\"\"\n        Match only documents where the query terms appear in\n        the same order in the document.\n        i.e. for the query \"hello world\", we do not match \"world hello\"\n        \"\"\"\n        self._in_order = True\n        return self\n\n    def scorer(self, scorer):\n        \"\"\"\n        Use a different scoring function to evaluate document relevance.\n        Default is `TFIDF`.\n\n        :param scorer: The scoring function to use\n                       (e.g. `TFIDF.DOCNORM` or `BM25`)\n        \"\"\"\n        self._scorer = scorer\n        return self\n\n    def get_args(self):\n        \"\"\"Format the redis arguments for this query and return them.\"\"\"\n        args = [self._query_string]\n        args += self._get_args_tags()\n        args += self._summarize_fields + self._highlight_fields\n        args += [\"LIMIT\", self._offset, self._num]\n        return args\n\n    def _get_args_tags(self):\n        args = []\n        if self._no_content:\n            args.append(\"NOCONTENT\")\n        if self._fields:\n            args.append(\"INFIELDS\")\n            args.append(len(self._fields))\n            args += self._fields\n        if self._verbatim:\n            args.append(\"VERBATIM\")\n        if self._no_stopwords:\n            args.append(\"NOSTOPWORDS\")\n        if self._filters:\n            for flt in self._filters:\n                if not isinstance(flt, Filter):\n                    raise AttributeError(\"Did not receive a Filter object.\")\n                args += flt.args\n        if self._with_payloads:\n            args.append(\"WITHPAYLOADS\")\n        if self._scorer:\n            args += [\"SCORER\", self._scorer]\n        if self._with_scores:\n            args.append(\"WITHSCORES\")\n        if self._ids:\n            args.append(\"INKEYS\")\n            args.append(len(self._ids))\n            args += self._ids\n        if self._slop >= 0:\n            args += [\"SLOP\", self._slop]\n        if self._in_order:\n            args.append(\"INORDER\")\n        if self._return_fields:\n            args.append(\"RETURN\")\n            args.append(len(self._return_fields))\n            args += self._return_fields\n        if self._sortby:\n            if not isinstance(self._sortby, SortbyField):\n                raise AttributeError(\"Did not receive a SortByField.\")\n            args.append(\"SORTBY\")\n            args += self._sortby.args\n        if self._language:\n            args += [\"LANGUAGE\", self._language]\n        if self._expander:\n            args += [\"EXPANDER\", self._expander]\n        if self._dialect:\n            args += [\"DIALECT\", self._dialect]\n\n        return args\n\n    def paging(self, offset, num):\n        \"\"\"\n        Set the paging for the query (defaults to 0..10).\n\n        - **offset**: Paging offset for the results. Defaults to 0\n        - **num**: How many results do we want\n        \"\"\"\n        self._offset = offset\n        self._num = num\n        return self\n\n    def verbatim(self):\n        \"\"\"Set the query to be verbatim, i.e. use no query expansion\n        or stemming.\n        \"\"\"\n        self._verbatim = True\n        return self\n\n    def no_content(self):\n        \"\"\"Set the query to only return ids and not the document content.\"\"\"\n        self._no_content = True\n        return self\n\n    def no_stopwords(self):\n        \"\"\"\n        Prevent the query from being filtered for stopwords.\n        Only useful in very big queries that you are certain contain\n        no stopwords.\n        \"\"\"\n        self._no_stopwords = True\n        return self\n\n    def with_payloads(self):\n        \"\"\"Ask the engine to return document payloads.\"\"\"\n        self._with_payloads = True\n        return self\n\n    def with_scores(self):\n        \"\"\"Ask the engine to return document search scores.\"\"\"\n        self._with_scores = True\n        return self\n\n    def limit_fields(self, *fields):\n        \"\"\"\n        Limit the search to specific TEXT fields only.\n\n        - **fields**: A list of strings, case sensitive field names\n        from the defined schema.\n        \"\"\"\n        self._fields = fields\n        return self\n\n    def add_filter(self, flt):\n        \"\"\"\n        Add a numeric or geo filter to the query.\n        **Currently only one of each filter is supported by the engine**\n\n        - **flt**: A NumericFilter or GeoFilter object, used on a\n        corresponding field\n        \"\"\"\n\n        self._filters.append(flt)\n        return self\n\n    def sort_by(self, field, asc=True):\n        \"\"\"\n        Add a sortby field to the query.\n\n        - **field** - the name of the field to sort by\n        - **asc** - when `True`, sorting will be done in asceding order\n        \"\"\"\n        self._sortby = SortbyField(field, asc)\n        return self\n\n    def expander(self, expander):\n        \"\"\"\n        Add a expander field to the query.\n\n        - **expander** - the name of the expander\n        \"\"\"\n        self._expander = expander\n        return self\n\n    def dialect(self, dialect: int) -> \"Query\":\n        \"\"\"\n        Add a dialect field to the query.\n\n        - **dialect** - dialect version to execute the query under\n        \"\"\"\n        self._dialect = dialect\n        return self\n\n\nclass Filter:\n    def __init__(self, keyword, field, *args):\n        self.args = [keyword, field] + list(args)\n\n\nclass NumericFilter(Filter):\n    INF = \"+inf\"\n    NEG_INF = \"-inf\"\n\n    def __init__(self, field, minval, maxval, minExclusive=False, maxExclusive=False):\n        args = [\n            minval if not minExclusive else f\"({minval}\",\n            maxval if not maxExclusive else f\"({maxval}\",\n        ]\n\n        Filter.__init__(self, \"FILTER\", field, *args)\n\n\nclass GeoFilter(Filter):\n    METERS = \"m\"\n    KILOMETERS = \"km\"\n    FEET = \"ft\"\n    MILES = \"mi\"\n\n    def __init__(self, field, lon, lat, radius, unit=KILOMETERS):\n        Filter.__init__(self, \"GEOFILTER\", field, lon, lat, radius, unit)\n\n\nclass SortbyField:\n    def __init__(self, field, asc=True):\n        self.args = [field, \"ASC\" if asc else \"DESC\"]\n", "path": "redis/commands/search/query.py"}]}