1# RediSearch Full Command Documentation
2
3## FT.CREATE
4
5### Format
6```
7  FT.CREATE {index}
8    [MAXTEXTFIELDS] [TEMPORARY {seconds}] [NOOFFSETS] [NOHL] [NOFIELDS] [NOFREQS]
9    [STOPWORDS {num} {stopword} ...]
10    SCHEMA {field} [TEXT [NOSTEM] [WEIGHT {weight}] [PHONETIC {matcher}] | NUMERIC | GEO | TAG [SEPARATOR {sep}] ] [SORTABLE][NOINDEX] ...
11```
12
13### Description
14Creates an index with the given spec. The index name will be used in all the key names so keep it short!
15
16!!! warning "Note on field number limits"
17
18        RediSearch supports up to 1024 fields per schema, out of which at most 128 can be TEXT fields.
19
20        On 32 bit builds, at most 64 fields can be TEXT fields.
21
22        Note that the more fields you have, the larger your index will be, as each additional 8 fields require one extra byte per index record to encode.
23
24        You can always use the `NOFIELDS` option and not encode field information into the index, for saving space, if you do not need filtering by text fields. This will still allow filtering by numeric and geo fields.
25
26!!! info "Note on running in clustered databases"
27
28        When having several indices in a clustered database, you need to tag the index key and the document key to ensure they reside on the same shard.
29
30	```
31        FT.CREATE {idx} ...
32        FT.ADD {idx} {idx}:docid ...
33        ```
34
35        When Running in RediSearch in Redis Enterprise, there is the ability to span the index across shards.  In this case the above does not apply.
36
37#### Example
38```sql
39FT.CREATE idx SCHEMA name TEXT SORTABLE age NUMERIC SORTABLE myTag TAG SORTABLE
40```
41
42### Parameters
43
44* **index**: the index name to create. If it exists the old spec will be overwritten
45
46* **MAXTEXTFIELDS**: For efficiency, RediSearch encodes indexes differently if they are
47  created with less than 32 text fields. This option forces RediSearch to encode indexes as if
48  there were more than 32 text fields, which allows you to add additional fields (beyond 32)
49  using `FT.ALTER`.
50
51* **NOOFFSETS**: If set, we do not store term offsets for documents (saves memory, does not
52  allow exact searches or highlighting). Implies `NOHL`.
53
54* **TEMPORARY**: Create a lightweight temporary index which will expire after the specified period of inactivity. The internal idle timer is reset whenever the index is searched or added to. Because such indexes are lightweight, you can create thousands of such indexes without negative performance implications.
55
56* **NOHL**: Conserves storage space and memory by disabling highlighting support. If set, we do
57  not store corresponding byte offsets for term positions. `NOHL` is also implied by `NOOFFSETS`.
58
59* **NOFIELDS**: If set, we do not store field bits for each term. Saves memory, does not allow
60  filtering by specific fields.
61
62* **NOFREQS**: If set, we avoid saving the term frequencies in the index. This saves
63  memory but does not allow sorting based on the frequencies of a given term within
64  the document.
65
66* **STOPWORDS**: If set, we set the index with a custom stopword list, to be ignored during
67  indexing and search time. {num} is the number of stopwords, followed by a list of stopword
68  arguments exactly the length of {num}.
69
70    If not set, we take the default list of stopwords.
71
72    If **{num}** is set to 0, the index will not have stopwords.
73
74* **SCHEMA {field} {options...}**: After the SCHEMA keyword we define the index fields. They
75  can be numeric, textual or geographical. For textual fields we optionally specify a weight.
76  The default weight is 1.0.
77
78    ### Field Options
79
80
81    * **SORTABLE**
82
83        Numeric, tag or text field can have the optional SORTABLE argument that allows the user to later [sort the results by the value of this field](Sorting.md) (this adds memory overhead so do not declare it on large text fields).
84
85    * **NOSTEM**
86
87        Text fields can have the NOSTEM argument which will disable stemming when indexing its values.
88        This may be ideal for things like proper names.
89
90    * **NOINDEX**
91
92        Fields can have the `NOINDEX` option, which means they will not be indexed.
93        This is useful in conjunction with `SORTABLE`, to create fields whose update using PARTIAL will not cause full reindexing of the document. If a field has NOINDEX and doesn't have SORTABLE, it will just be ignored by the index.
94
95    * **PHONETIC {matcher}**
96
97        Declaring a text field as `PHONETIC` will perform phonetic matching on it in searches by default. The obligatory {matcher} argument specifies the phonetic algorithm and language used. The following matchers are supported:
98
99        * `dm:en` - Double Metaphone for English
100        * `dm:fr` - Double Metaphone for French
101        * `dm:pt` - Double Metaphone for Portuguese
102        * `dm:es` - Double Metaphone for Spanish
103
104        For more details see [Phonetic Matching](Phonetic_Matching.md).
105
106    * **WEIGHT {weight}**
107
108        For `TEXT` fields, declares the importance of this field when
109        calculating result accuracy. This is a multiplication factor, and
110        defaults to 1 if not specified.
111
112    * **SEPARATOR {sep}**
113
114        For `TAG` fields, indicates how the text contained in the field
115        is to be split into individual tags. The default is `,`. The value
116        must be a single character.
117
118
119
120### Complexity
121O(1)
122
123### Returns
124OK or an error
125
126---
127
128## FT.ADD
129
130### Format
131
132```
133FT.ADD {index} {docId} {score}
134  [NOSAVE]
135  [REPLACE [PARTIAL] [NOCREATE]]
136  [LANGUAGE {language}]
137  [PAYLOAD {payload}]
138  [IF {condition}]
139  FIELDS {field} {value} [{field} {value}...]
140```
141
142### Description
143
144Adds a document to the index.
145
146#### Example
147```sql
148FT.ADD idx doc1 1.0 FIELDS title "hello world"
149```
150
151### Parameters
152
153- **index**: The Fulltext index name. The index must be first created with FT.CREATE
154
155- **docId**: The document's id that will be returned from searches.
156
157!!! note "Notes on docId"
158
159        The same docId cannot be added twice to the same index.
160
161        The same docId can be added to multiple indices, but a single document with that docId is saved in the database.
162
163- **score**: The document's rank based on the user's ranking. This must be between 0.0 and 1.0.
164  If you don't have a score just set it to 1
165
166- **NOSAVE**: If set to true, we will not save the actual document in the database and only index it.
167
168- **REPLACE**: If set, we will do an UPSERT style insertion - and delete an older version of the
169  document if it exists.
170
171- **PARTIAL** (only applicable with REPLACE): If set, you do not have to specify all fields for
172  reindexing. Fields not given to the command will be loaded from the current version of the
173  document. Also, if only non-indexable fields, score or payload are set - we do not do a full
174  re-indexing of the document, and this will be a lot faster.
175
176- **NOCREATE** (only applicable with REPLACE): If set, the document is only updated
177  and reindexed if it already exists. If the document does not exist, an error
178  will be returned.
179
180- **FIELDS**: Following the FIELDS specifier, we are looking for pairs of  `{field} {value}` to be
181  indexed. Each field will be scored based on the index spec given in `FT.CREATE`.
182  Passing fields that are not in the index spec will make them be stored as part of the document,
183  or ignored if NOSAVE is set
184
185- **PAYLOAD {payload}**: Optionally set a binary safe payload string to the document,
186  that can be evaluated at query time by a custom scoring function, or retrieved to the client.
187
188- **IF {condition}**: (Applicable only in conjunction with `REPLACE` and optionally `PARTIAL`).
189  Update the document only if a boolean expression applies to the document **before the update**,
190  e.g. `FT.ADD idx doc 1 REPLACE IF "@timestamp < 23323234234"`.
191
192  The expression is evaluated atomically before the update, ensuring that the update will happen only if it is true.
193
194  See [Aggregations](Aggregations.md) for more details on the expression language.
195
196- **LANGUAGE language**: If set, we use a stemmer for the supplied language during indexing. Default
197  to English.
198  If an unsupported language is sent, the command returns an error.
199  The supported languages are:
200
201    > "arabic",  "danish",    "dutch",   "english",   "finnish",    "french",
202    > "german",  "hungarian", "italian", "norwegian", "portuguese", "romanian",
203    > "russian", "spanish",   "swedish", "tamil",     "turkish"
204    > "chinese"
205
206  If indexing a Chinese language document, you must set the language to `chinese`
207  in order for Chinese characters to be tokenized properly.
208
209### Adding Chinese Documents
210
211When adding Chinese-language documents, `LANGUAGE chinese` should be set in
212order for the indexer to properly tokenize the terms. If the default language
213is used then search terms will be extracted based on punctuation characters and
214whitespace. The Chinese language tokenizer makes use of a segmentation algorithm
215(via [Friso](https://github.com/lionsoul2014/friso)) which segments texts and
216checks it against a predefined dictionary. See [Stemming](Stemming.md) for more
217information.
218
219### Complexity
220
221O(n), where n is the number of tokens in the document
222
223### Returns
224
225OK on success, or an error if something went wrong.
226
227A special status `NOADD` is returned if an `IF` condition evaluated to false.
228
229!!! warning "FT.ADD with REPLACE and PARTIAL"
230
231        By default, FT.ADD does not allow updating the document, and will fail if it already exists in the index.
232
233        However, updating the document is possible with the REPLACE and REPLACE PARTIAL options.
234
235        **REPLACE**: On its own, sets the document to the new values, and reindexes it. Any fields not given will not be loaded from the current version of the document.
236
237        **REPLACE PARTIAL**: When both arguments are used, we can update just part of the document fields, and the rest will be loaded before reindexing. Not only that, but if only the score, payload and non-indexed fields (using NOINDEX) are updated, we will not actually reindex the document, just update its metadata internally, which is a lot faster and does not create index garbage.
238
239---
240
241### Warning!!!
242
243FT.ADD will actually create a hash in Redis with the given fields and value. This means that if the hash already exists, it will override with the new values. Moreover, if you try to add a document with the same id to two different indexes one of them will override the other and you will get wrong responses from one of the indexes.
244For this reason, it is recommended to create global unique documents ids (this can e.g. be achieved by adding the index name to the document id as prefix).
245
246## FT.ADDHASH
247
248### Format
249
250```
251 FT.ADDHASH {index} {docId} {score} [LANGUAGE language] [REPLACE]
252```
253
254### Description
255
256Adds a document to the index from an existing HASH key in Redis.
257
258#### Example
259```sql
260FT.ADDHASH idx hash1 1.0 REPLACE
261```
262
263### Parameters
264
265- **index**: The Fulltext index name. The index must be first created with FT.CREATE
266
267-  **docId**: The document's id. This has to be an existing HASH key in Redis that will hold the fields
268    the index needs.
269
270- **score**: The document's rank based on the user's ranking. This must be between 0.0 and 1.0.
271  If you don't have a score just set it to 1
272
273- **REPLACE**: If set, we will do an UPSERT style insertion - and delete an older version of the document if it exists.
274
275- **LANGUAGE language**: If set, we use a stemmer for the supplied language during indexing. Defaults
276  to English.
277  If an unsupported language is sent, the command returns an error.
278  The supported languages are:
279
280  > "arabic",  "danish",    "dutch",   "english",   "finnish",    "french",
281  > "german",  "hungarian", "italian", "norwegian", "portuguese", "romanian",
282  > "russian", "spanish",   "swedish", "tamil",     "turkish"
283
284### Complexity
285
286O(n), where n is the number of tokens in the document
287
288### Returns
289
290OK on success, or an error if something went wrong.
291
292---
293
294## FT.ALTER SCHEMA ADD
295
296### Format
297
298```
299FT.ALTER {index} SCHEMA ADD {field} {options} ...
300```
301
302### Description
303
304Adds a new field to the index.
305
306Adding a field to the index will cause any future document updates to use the new field when
307indexing. Existing documents will not be reindexed.
308
309!!! note
310    Depending on how the index was created, you may be limited by the amount of additional text
311    fields which can be added to an existing index. If the current index contains less than 32
312    text fields, then `SCHEMA ADD` will only be able to add up to 32 fields (meaning that the
313    index will only ever be able to contain 32 total text fields). If you wish for the index to
314    contain more than 32 fields, create it with the `MAXTEXTFIELDS` option.
315
316#### Example
317```sql
318FT.ALTER idx SCHEMA ADD id2 NUMERIC SORTABLE
319```
320
321### Parameters
322
323* **index**: the index name.
324* **field**: the field name.
325* **options**: the field options - refer to `FT.CREATE` for more information.
326
327### Complexity
328
329O(1)
330
331### Returns
332
333OK or an error.
334
335
336---
337
338## FT.ALIASADD
339## FT.ALIASUPDATE
340## FT.ALIASDEL
341
342### Format
343
344```
345FT.ALIASADD {name} {index}
346FT.ALIASUPDATE {name} {index}
347FT.ALIASDEL {name}
348```
349
350The `FT.ALIASADD` and `FT.ALIASDEL` commands will add or remove an alias from
351an index. Index aliases can be used to refer to actual indexes in data
352commands such as `FT.SEARCH` or `FT.ADD`. This allows an administrator
353to transparently redirect application queries to alternative indexes.
354
355Indexes can have more than one alias, though an alias cannot refer to another
356alias.
357
358The `FT.ALIASUPDATE` command differs from the `FT.ALIASADD` command in that
359it will remove the alias association with a previous index, if any. `FT.ALIASDD`
360will fail, on the other hand, if the alias is already associated with another
361index.
362
363### Complexity
364
365O(1)
366
367### Returns
368
369OK or an error.
370
371---
372
373## FT.INFO
374
375### Format
376
377```
378FT.INFO {index}
379```
380
381### Description
382
383Returns information and statistics on the index. Returned values include:
384
385* Number of documents.
386* Number of distinct terms.
387* Average bytes per record.
388* Size and capacity of the index buffers.
389
390#### Example
391```bash
392127.0.0.1:6379> ft.info wik{0}
393 1) index_name
394 2) wikipedia
395 3) fields
396 4) 1) 1) title
397       2) type
398       3) FULLTEXT
399       4) weight
400       5) "1"
401    2) 1) body
402       2) type
403       3) FULLTEXT
404       4) weight
405       5) "1"
406 5) num_docs
407 6) "502694"
408 7) num_terms
409 8) "439158"
410 9) num_records
41110) "8098583"
41211) inverted_sz_mb
41312) "45.58
41413) inverted_cap_mb
41514) "56.61
41615) inverted_cap_ovh
41716) "0.19
41817) offset_vectors_sz_mb
41918) "9.27
42019) skip_index_size_mb
42120) "7.35
42221) score_index_size_mb
42322) "30.8
42423) records_per_doc_avg
42524) "16.1
42625) bytes_per_record_avg
42726) "5.90
42827) offsets_per_term_avg
42928) "1.20
43029) offset_bits_per_record_avg
43130) "8.00
432```
433
434### Parameters
435
436- **index**: The Fulltext index name. The index must be first created with FT.CREATE
437
438### Complexity
439
440O(1)
441
442### Returns
443
444Array Response. A nested array of keys and values.
445
446---
447
448## FT.SEARCH
449
450### Format
451
452```
453FT.SEARCH {index} {query} [NOCONTENT] [VERBATIM] [NOSTOPWORDS] [WITHSCORES] [WITHPAYLOADS] [WITHSORTKEYS]
454  [FILTER {numeric_field} {min} {max}] ...
455  [GEOFILTER {geo_field} {lon} {lat} {radius} m|km|mi|ft]
456  [INKEYS {num} {key} ... ]
457  [INFIELDS {num} {field} ... ]
458  [RETURN {num} {field} ... ]
459  [SUMMARIZE [FIELDS {num} {field} ... ] [FRAGS {num}] [LEN {fragsize}] [SEPARATOR {separator}]]
460  [HIGHLIGHT [FIELDS {num} {field} ... ] [TAGS {open} {close}]]
461  [SLOP {slop}] [INORDER]
462  [LANGUAGE {language}]
463  [EXPANDER {expander}]
464  [SCORER {scorer}] [EXPLAINSCORE]
465  [PAYLOAD {payload}]
466  [SORTBY {field} [ASC|DESC]]
467  [LIMIT offset num]
468```
469
470### Description
471
472Searches the index with a textual query, returning either documents or just ids.
473
474### Example
475```sql
476FT.SEARCH idx "@text:morphix=>{$phonetic:false}"
477```
478
479### Parameters
480
481- **index**: The index name. The index must be first created with `FT.CREATE`.
482- **query**: the text query to search. If it's more than a single word, put it in quotes.
483  Refer to [query syntax](Query_Syntax.md) for more details.
484
485- **NOCONTENT**: If it appears after the query, we only return the document ids and not
486  the content. This is useful if RediSearch is only an index on an external document collection
487- **VERBATIM**: if set, we do not try to use stemming for query expansion but search the query terms
488  verbatim.
489- **NOSTOPWORDS**: If set, we do not filter stopwords from the query.
490- **WITHSCORES**: If set, we also return the relative internal score of each document. this can be
491  used to merge results from multiple instances
492- **WITHPAYLOADS**: If set, we retrieve optional document payloads (see FT.ADD).
493  the payloads follow the document id, and if `WITHSCORES` was set, follow the scores.
494- **WITHSORTKEYS**: Only relevant in conjunction with **SORTBY**. Returns the value of the sorting key,
495  right after the id and score and /or payload if requested. This is usually not needed by users, and
496  exists for distributed search coordination purposes.
497
498- **FILTER numeric_field min max**: If set, and numeric_field is defined as a numeric field in
499  FT.CREATE, we will limit results to those having numeric values ranging between min and max.
500  min and max follow ZRANGE syntax, and can be **-inf**, **+inf** and use `(` for exclusive ranges.
501  Multiple numeric filters for different fields are supported in one query.
502- **GEOFILTER {geo_field} {lon} {lat} {radius} m|km|mi|ft**: If set, we filter the results to a given radius
503  from lon and lat. Radius is given as a number and units. See [GEORADIUS](https://redis.io/commands/georadius)
504  for more details.
505- **INKEYS {num} {field} ...**: If set, we limit the result to a given set of keys specified in the
506  list.
507  the first argument must be the length of the list, and greater than zero.
508  Non-existent keys are ignored - unless all the keys are non-existent.
509- **INFIELDS {num} {field} ...**: If set, filter the results to ones appearing only in specific
510  fields of the document, like title or URL. num is the number of specified field arguments
511
512- **RETURN {num} {field} ...**: Use this keyword to limit which fields from the document are returned.
513  `num` is the number of fields following the keyword. If `num` is 0, it acts like `NOCONTENT`.
514- **SUMMARIZE ...**: Use this option to return only the sections of the field which contain the
515  matched text.
516  See [Highlighting](Highlight.md) for more details
517- **HIGHLIGHT ...**: Use this option to format occurrences of matched text. See [Highligting](Highlight.md) for more
518  details
519- **SLOP {slop}**: If set, we allow a maximum of N intervening number of unmatched offsets between
520  phrase terms. (i.e the slop for exact phrases is 0)
521- **INORDER**: If set, and usually used in conjunction with SLOP, we make sure the query terms appear
522  in the same order in the document as in the query, regardless of the offsets between them.
523- **LANGUAGE {language}**: If set, we use a stemmer for the supplied language during search for query
524  expansion.
525  If querying documents in Chinese, this should be set to `chinese` in order to
526  properly tokenize the query terms.
527  Defaults to English. If an unsupported language is sent, the command returns an error.
528  See FT.ADD for the list of languages.
529
530- **EXPANDER {expander}**: If set, we will use a custom query expander instead of the stemmer. [See Extensions](Extensions.md).
531- **SCORER {scorer}**: If set, we will use a custom scoring function defined by the user. [See Extensions](Extensions.md).
532- **EXPLAINSCORE**: If set, will return a textual description of how the scores were calculated.
533- **PAYLOAD {payload}**: Add an arbitrary, binary safe payload that will be exposed to custom scoring
534  functions. [See Extensions](Extensions.md).
535
536- **SORTBY {field} [ASC|DESC]**: If specified, the results
537  are ordered by the value of this field. This applies to both text and numeric fields.
538- **LIMIT first num**: If the parameters appear after the query, we limit the results to
539  the offset and number of results given. The default is 0 10.
540  Note that you can use `LIMIT 0 0` to count the number of documents in
541  the resultset without actually returning them.
542
543### Complexity
544
545O(n) for single word queries. `n` is the number of the results in the result set. Finding all the documents that have a specific term is O(1), however, a scan on all those documents is needed to load the documents data from redis hashes and return them.
546
547The time complexity for more complex queries varies, but in general it's proportional to the number of words, the number of intersection points between them and the number of results in the result set.
548
549### Returns
550
551**Array reply,** where the first element is the total number of results, and then pairs of document id, and a nested array of field/value.
552
553If **NOCONTENT** was given, we return an array where the first element is the total number of results, and the rest of the members are document ids.
554
555---
556
557## FT.AGGREGATE
558
559### Format
560
561```
562FT.AGGREGATE  {index_name}
563  {query_string}
564  [VERBATIM]
565  [LOAD {nargs} {property} ...]
566  [GROUPBY {nargs} {property} ...
567    REDUCE {func} {nargs} {arg} ... [AS {name:string}]
568    ...
569  ] ...
570  [SORTBY {nargs} {property} [ASC|DESC] ... [MAX {num}]]
571  [APPLY {expr} AS {alias}] ...
572  [LIMIT {offset} {num}] ...
573  [FILTER {expr}] ...
574```
575
576### Description
577
578Runs a search query on an index, and performs aggregate transformations on the results, extracting statistics etc from them. See [the full documentation on aggregations](Aggregations.md) for further details.
579
580### Example
581```sql
582FT.AGGREGATE idx "@url:\"about.html\""
583    APPLY "@timestamp - (@timestamp % 86400)" AS day
584    GROUPBY 2 @day @country
585    	REDUCE count 0 AS num_visits
586    SORTBY 4 @day ASC @country DESC
587```
588
589### Parameters
590
591* **index_name**: The index the query is executed against.
592
593* **query_string**: The base filtering query that retrieves the documents. It follows
594  **the exact same syntax** as the search query, including filters, unions, not, optional, etc.
595
596* **LOAD {nargs} {property} …**: Load document fields from the document HASH objects. This should be
597  avoided as a general rule of thumb. Fields needed for aggregations should be stored as **SORTABLE**,
598  where they are available to the aggregation pipeline with very low latency. LOAD hurts the
599  performance of aggregate queries considerably, since every processed record needs to execute the
600  equivalent of HMGET against a Redis key, which when executed over millions of keys, amounts to very
601  high processing times.
602
603* **GROUPBY {nargs} {property}**: Group the results in the pipeline based on one or more properties.
604  Each group should have at least one reducer (See below), a function that handles the group entries,
605  either counting them, or performing multiple aggregate operations (see below).
606    * **REDUCE {func} {nargs} {arg} … [AS {name}]**: Reduce the matching results in each group into a single record, using a reduction function. For example COUNT will count the number of records in the group. See the Reducers section below for more details on available reducers.
607
608          The reducers can have their own property names using the `AS {name}` optional argument. If a name is not given, the resulting name will be the name of the reduce function and the group properties. For example, if a name is not given to COUNT_DISTINCT by property `@foo`, the resulting name will be `count_distinct(@foo)`.
609
610* **SORTBY {nargs} {property} {ASC|DESC} [MAX {num}]**: Sort the pipeline up until the point of SORTBY,
611  using a list of properties. By default, sorting is ascending, but `ASC` or `DESC ` can be added for
612  each property. `nargs` is the number of sorting parameters, including ASC and DESC. for example:
613  `SORTBY 4 @foo ASC @bar DESC`.
614
615    `MAX` is used to optimized sorting, by sorting only for the n-largest elements. Although it is not connected to `LIMIT`, you usually need just `SORTBY … MAX` for common queries.
616
617* **APPLY {expr} AS {name}**: Apply a 1-to-1 transformation on one or more properties, and either
618  store the result as a new property down the pipeline, or replace any property using this
619  transformation. `expr` is an expression that can be used to perform arithmetic operations on numeric
620  properties, or functions that can be applied on properties depending on their types (see below), or
621  any combination thereof. For example: `APPLY "sqrt(@foo)/log(@bar) + 5" AS baz` will evaluate this
622  expression dynamically for each record in the pipeline and store the result as a new property called
623  baz, that can be referenced by further APPLY / SORTBY / GROUPBY / REDUCE operations down the
624  pipeline.
625
626* **LIMIT {offset} {num}**. Limit the number of results to return just `num` results starting at index
627  `offset` (zero-based). AS mentioned above, it is much more efficient to use `SORTBY … MAX` if you
628  are interested in just limiting the output of a sort operation.
629
630    However, limit can be used to limit results without sorting, or for paging the n-largest results as determined by `SORTBY MAX`. For example, getting results 50-100 of the top 100 results is most efficiently expressed as `SORTBY 1 @foo MAX 100 LIMIT 50 50`. Removing the MAX from SORTBY will result in the pipeline sorting _all_ the records and then paging over results 50-100.
631
632* **FILTER {expr}**. Filter the results using predicate expressions relating to values in each result.
633  They are is applied post-query and relate to the current state of the pipeline.
634
635### Complexity
636
637Non-deterministic. Depends on the query and aggregations performed, but it is usually linear to the number of results returned.
638
639### Returns
640
641Array Response. Each row is an array and represents a single aggregate result.
642
643### Example output
644
645Here we are counting GitHub events by user (actor), to produce the most active users:
646
647```sh
648127.0.0.1:6379> FT.AGGREGATE gh "*" GROUPBY 1 @actor REDUCE COUNT 0 AS num SORTBY 2 @num DESC MAX 10
649 1) (integer) 284784
650 2) 1) "actor"
651    2) "lombiqbot"
652    3) "num"
653    4) "22197"
654 3) 1) "actor"
655    2) "codepipeline-test"
656    3) "num"
657    4) "17746"
658 4) 1) "actor"
659    2) "direwolf-github"
660    3) "num"
661    4) "10683"
662 5) 1) "actor"
663    2) "ogate"
664    3) "num"
665    4) "6449"
666 6) 1) "actor"
667    2) "openlocalizationtest"
668    3) "num"
669    4) "4759"
670 7) 1) "actor"
671    2) "digimatic"
672    3) "num"
673    4) "3809"
674 8) 1) "actor"
675    2) "gugod"
676    3) "num"
677    4) "3512"
678 9) 1) "actor"
679    2) "xdzou"
680    3) "num"
681    4) "3216"
68210) 1) "actor"
683    2) "opstest"
684    3) "num"
685    4) "2863"
68611) 1) "actor"
687    2) "jikker"
688    3) "num"
689    4) "2794"
690(0.59s)
691```
692
693---
694
695## FT.EXPLAIN
696
697### Format
698
699```
700FT.EXPLAIN {index} {query}
701```
702
703### Description
704
705Returns the execution plan for a complex query.
706
707In the returned response, a `+` on a term is an indication of stemming.
708
709### Example
710```sh
711$ redis-cli --raw
712
713127.0.0.1:6379> FT.EXPLAIN rd "(foo bar)|(hello world) @date:[100 200]|@date:[500 +inf]"
714INTERSECT {
715  UNION {
716    INTERSECT {
717      foo
718      bar
719    }
720    INTERSECT {
721      hello
722      world
723    }
724  }
725  UNION {
726    NUMERIC {100.000000 <= x <= 200.000000}
727    NUMERIC {500.000000 <= x <= inf}
728  }
729}
730```
731
732### Parameters
733
734- **index**: The index name. The index must be first created with FT.CREATE
735- **query**: The query string, as if sent to FT.SEARCH
736
737### Complexity
738
739O(1)
740
741### Returns
742
743String Response. A string representing the execution plan (see above example).
744
745**Note**: You should use `redis-cli --raw` to properly read line-breaks in the returned response.
746
747---
748
749## FT.EXPLAINCLI
750
751### Format
752
753```
754FT.EXPLAINCLI {index} {query}
755```
756
757### Description
758
759Returns the execution plan for a complex query but formatted for easier reading without using `redis-cli --raw`.
760
761In the returned response, a `+` on a term is an indication of stemming.
762
763### Example
764```sh
765$ redis-cli
766
767127.0.0.1:6379> FT.EXPLAINCLI rd "(foo bar)|(hello world) @date:[100 200]|@date:[500 +inf]"
768 1) INTERSECT {
769 2)   UNION {
770 3)     INTERSECT {
771 4)       UNION {
772 5)         foo
773 6)         +foo(expanded)
774 7)       }
775 8)       UNION {
776 9)         bar
77710)         +bar(expanded)
77811)       }
77912)     }
78013)     INTERSECT {
78114)       UNION {
78215)         hello
78316)         +hello(expanded)
78417)       }
78518)       UNION {
78619)         world
78720)         +world(expanded)
78821)       }
78922)     }
79023)   }
79124)   UNION {
79225)     NUMERIC {100.000000 <= @date <= 200.000000}
79326)     NUMERIC {500.000000 <= @date <= inf}
79427)   }
79528) }
79629)
797```
798
799### Parameters
800
801- **index**: The index name. The index must be first created with FT.CREATE
802- **query**: The query string, as if sent to FT.SEARCH
803
804### Complexity
805
806O(1)
807
808### Returns
809
810String Response. A string representing the execution plan (see above example).
811
812---
813
814## FT.DEL
815
816### Format
817
818```
819FT.DEL {index} {doc_id} [DD]
820```
821
822### Description
823
824Deletes a document from the index. Returns 1 if the document was in the index, or 0 if not.
825
826After deletion, the document can be re-added to the index. It will get a different internal id and will be a new document from the index's POV.
827
828!!! warning "FT.DEL does not delete the actual document By default!"
829
830        Since RediSearch regards documents as separate entities to the index and allows things like adding existing documents or indexing without saving the document - by default FT.DEL only deletes the reference to the document from the index, not the actual Redis HASH key where the document is stored.
831
832        Specifying **DD** (Delete Document) after the document ID, will make RediSearch also delete the actual document **if it is in the index**.
833
834        Alternatively, you can just send an extra **DEL {doc_id}** to redis and delete the document directly. You can run both of them in a MULTI transaction.
835
836### Example
837```sql
838FT.DEL idx doc1
839```
840
841### Parameters
842
843- **index**: The index name. The index must be first created with FT.CREATE
844- **doc_id**: the id of the document to be deleted. It does not actually delete the HASH key in which
845  the document is stored. Use DEL to do that manually if needed.
846
847
848### Complexity
849
850O(1)
851
852### Returns
853
854Integer Reply: 1 if the document was deleted, 0 if not.
855
856---
857
858## FT.GET
859
860### Format
861
862```
863FT.GET {index} {doc id}
864```
865
866### Description
867
868Returns the full contents of a document.
869
870Currently it is equivalent to HGETALL, but this is future-proof and will allow us to change the internal representation of documents inside Redis in the future. In addition, it allows simpler implementation of fetching documents in clustered mode.
871
872If the document does not exist or is not a HASH object, we return a NULL reply
873
874### Example
875```sql
876FT.GET idx doc1
877```
878
879### Parameters
880
881- **index**: The index name. The index must be first created with FT.CREATE
882- **documentId**: The id of the document as inserted to the index
883
884### Returns
885
886Array Reply: Key-value pairs of field names and values of the document
887
888---
889
890## FT.MGET
891
892### Format
893
894```
895FT.MGET {index} {docId} ...
896```
897
898### Description
899
900Returns the full contents of multiple documents.
901
902Currently it is equivalent to calling multiple HGETALL commands, although faster.
903This command is also future-proof and will allow us to change the internal representation of documents inside Redis in the future.
904In addition, it allows simpler implementation of fetching documents in clustered mode.
905
906We return an array with exactly the same number of elements as the number of keys sent to the command.
907
908Each element, in turn, is an array of key-value pairs representing the document.
909
910If a document is not found or is not a valid HASH object, its place in the parent array is filled with a Null reply object.
911
912### Example
913```sql
914FT.MGET idx doc1 doc2
915```
916
917### Parameters
918
919- **index**: The Fulltext index name. The index must be first created with FT.CREATE
920- **documentIds**: The ids of the requested documents as inserted to the index
921
922### Returns
923
924Array Reply: An array with exactly the same number of elements as the number of keys sent to the command.  Each element in it is either an array representing the document or Null if it was not found.
925
926---
927
928## FT.DROP
929
930### Format
931
932```
933FT.DROP {index} [KEEPDOCS]
934```
935
936### Description
937
938Deletes all the keys associated with the index.
939
940By default, DROP deletes the document hashes as well, but adding the KEEPDOCS option keeps the documents in place, ready for re-indexing.
941
942If no other data is on the Redis instance, this is equivalent to FLUSHDB, apart from the fact
943that the index specification is not deleted.
944
945### Example
946```sql
947FT.DROP idx KEEPDOCS
948```
949
950### Parameters
951
952- **index**: The Fulltext index name. The index must be first created with FT.CREATE
953- **KEEPDOCS**: If set, the drop operation will not delete the actual document hashes.
954
955### Returns
956
957Status Reply: OK on success.
958
959---
960
961## FT.TAGVALS
962
963### Format
964
965```
966FT.TAGVALS {index} {field_name}
967```
968
969### Description
970
971Returns the distinct tags indexed in a [Tag field](Tags.md).
972
973This is useful if your tag field indexes things like cities, categories, etc.
974
975!!! warning "Limitations"
976
977      There is no paging or sorting, the tags are not alphabetically sorted.
978
979      This command only operates on [Tag fields](Tags.md).
980
981      The strings return lower-cased and stripped of whitespaces, but otherwise unchanged.
982
983### Example
984```sql
985FT.TAGVALS idx myTag
986```
987
988### Parameters
989
990- **index**: The Fulltext index name. The index must be first created with FT.CREATE
991- **filed_name**: The name of a Tag file defined in the schema.
992
993### Returns
994
995Array Reply: All the distinct tags in the tag index.
996
997### Complexity
998
999O(n), n being the cardinality of the tag field.
1000
1001---
1002
1003## FT.SUGADD
1004
1005### Format
1006
1007```
1008FT.SUGADD {key} {string} {score} [INCR] [PAYLOAD {payload}]
1009```
1010
1011### Description
1012
1013Adds a suggestion string to an auto-complete suggestion dictionary. This is disconnected from the
1014index definitions, and leaves creating and updating suggestions dictionaries to the user.
1015
1016### Example
1017```sql
1018FT.SUGADD ac "hello world" 1
1019```
1020
1021### Parameters
1022
1023- **key**: the suggestion dictionary key.
1024- **string**: the suggestion string we index
1025- **score**: a floating point number of the suggestion string's weight
1026- **INCR**: if set, we increment the existing entry of the suggestion by the given score, instead of
1027  replacing the score. This is useful for updating the dictionary based on user queries in real time
1028- **PAYLOAD {payload}**: If set, we save an extra payload with the suggestion, that can be fetched by
1029  adding the `WITHPAYLOADS` argument to `FT.SUGGET`.
1030
1031### Returns
1032
1033Integer Reply: the current size of the suggestion dictionary.
1034
1035---
1036
1037## FT.SUGGET
1038
1039### Format
1040
1041```
1042FT.SUGGET {key} {prefix} [FUZZY] [WITHSCORES] [WITHPAYLOADS] [MAX num]
1043```
1044
1045### Description
1046
1047Gets completion suggestions for a prefix.
1048
1049### Example
1050```sql
1051FT.SUGGET ac hell FUZZY MAX 3 WITHSCORES
1052```
1053
1054### Parameters
1055
1056- **key**: the suggestion dictionary key.
1057- **prefix**: the prefix to complete on
1058- **FUZZY**: if set, we do a fuzzy prefix search, including prefixes at Levenshtein distance of 1 from
1059  the prefix sent
1060- **MAX num**: If set, we limit the results to a maximum of `num` (default: 5).
1061- **WITHSCORES**: If set, we also return the score of each suggestion. this can be used to merge
1062  results from multiple instances
1063- **WITHPAYLOADS**: If set, we return optional payloads saved along with the suggestions. If no
1064  payload is present for an entry, we return a Null Reply.
1065
1066### Returns
1067
1068Array Reply: a list of the top suggestions matching the prefix, optionally with score after each entry
1069
1070---
1071
1072## FT.SUGDEL
1073
1074### Format
1075
1076```
1077FT.SUGDEL {key} {string}
1078```
1079
1080### Description
1081
1082Deletes a string from a suggestion index.
1083
1084### Example
1085```sql
1086FT.SUGDEL ac "hello world"
1087```
1088
1089### Parameters
1090
1091- **key**: the suggestion dictionary key.
1092- **string**: the string to delete
1093
1094### Returns
1095
1096Integer Reply: 1 if the string was found and deleted, 0 otherwise.
1097
1098---
1099
1100## FT.SUGLEN
1101
1102### Format
1103
1104```
1105FT.SUGLEN {key}
1106```
1107
1108### Description
1109
1110Gets the size of an auto-complete suggestion dictionary
1111
1112### Example
1113```sql
1114FT.SUGDEL ac
1115```
1116
1117### Parameters
1118
1119* **key**: the suggestion dictionary key.
1120
1121### Returns
1122
1123Integer Reply: the current size of the suggestion dictionary.
1124
1125---
1126
1127## FT.OPTIMIZE
1128
1129!!! warning "This command is deprecated"
1130    Index optimizations are done by the internal garbage collector in the background. Client libraries should not implement this command and remove it if they haven't already.
1131
1132### Format
1133
1134```
1135FT.OPTIMIZE {index}
1136```
1137
1138### Description
1139
1140This command is deprecated.
1141
1142---
1143
1144## FT.SYNADD
1145
1146### Format
1147
1148```
1149FT.SYNADD <index name> <term1> <term2> ...
1150```
1151
1152### Description
1153
1154Adds a synonym group.
1155
1156The command is used to create a new synonyms group. The command returns the synonym group id which can later be used to add additional terms to that synonym group. Only documents which were indexed after the adding operation will be affected.
1157
1158---
1159
1160## FT.SYNUPDATE
1161
1162### Format
1163
1164```
1165FT.SYNUPDATE <index name> <synonym group id> <term1> <term2> ...
1166```
1167
1168### Description
1169
1170Updates a synonym group.
1171
1172The command is used to update an existing synonym group with additional terms. Only documents which were indexed after the update will be affected.
1173
1174---
1175
1176## FT.SYNDUMP
1177
1178### Format
1179
1180```
1181FT.SYNDUMP <index name>
1182```
1183
1184### Description
1185
1186Dumps the contents of a synonym group.
1187
1188The command is used to dump the synonyms data structure. Returns a list of synonym terms and their synonym group ids.
1189
1190---
1191
1192## FT.SPELLCHECK
1193
1194### Format
1195```
1196  FT.SPELLCHECK {index} {query}
1197    [DISTANCE dist]
1198    [TERMS {INCLUDE | EXCLUDE} {dict} [TERMS ...]]
1199```
1200
1201### Description
1202
1203Performs spelling correction on a query, returning suggestions for misspelled terms.
1204
1205See [Query Spelling Correction](Spellcheck.md) for more details.
1206
1207### Parameters
1208
1209* **index**: the index with the indexed terms.
1210
1211* **query**: the search query.
1212
1213* **TERMS**: specifies an inclusion (`INCLUDE`) or exclusion (`EXCLUDE`) custom dictionary named `{dict}`. Refer to [`FT.DICTADD`](Commands.md#ftdictadd), [`FT.DICTDEL`](Commands.md#ftdictdel) and [`FT.DICTDUMP`](Commands.md#ftdictdump) for managing custom dictionaries.
1214
1215* **DISTANCE**: the maximal Levenshtein distance for spelling suggestions (default: 1, max: 4).
1216
1217### Returns
1218
1219An array, in which each element represents a misspelled term from the query. The misspelled terms are ordered by their order of appearance in the query.
1220
1221Each misspelled term, in turn, is a 3-element array consisting of the constant string "TERM", the term itself and an array of suggestions for spelling corrections.
1222
1223Each element in the spelling corrections array consists of the score of the suggestion and the suggestion itself. The suggestions array, per misspelled term, is ordered in descending order by score.
1224
1225### Example output
1226
1227```
12281)  1) "TERM"
1229    2) "{term1}"
1230    3)  1)  1)  "{score1}"
1231            2)  "{suggestion1}"
1232        2)  1)  "{score2}"
1233            2)  "{suggestion2}"
1234        .
1235        .
1236        .
12372)  1) "TERM"
1238    2) "{term2}"
1239    3)  1)  1)  "{score1}"
1240            2)  "{suggestion1}"
1241        2)  1)  "{score2}"
1242            2)  "{suggestion2}"
1243        .
1244        .
1245        .
1246.
1247.
1248.
1249
1250```
1251
1252---
1253
1254
1255## FT.DICTADD
1256
1257### Format
1258```
1259  FT.DICTADD {dict} {term} [{term} ...]
1260```
1261
1262### Description
1263
1264Adds terms to a dictionary.
1265
1266### Parameters
1267
1268* **dict**: the dictionary name.
1269
1270* **term**: the term to add to the dictionary.
1271
1272### Returns
1273
1274Returns int, specifically the number of new terms that were added.
1275
1276---
1277
1278## FT.DICTDEL
1279
1280### Format
1281```
1282  FT.DICTDEL {dict} {term} [{term} ...]
1283```
1284
1285### Description
1286
1287Deletes terms from a dictionary.
1288
1289### Parameters
1290
1291* **dict**: the dictionary name.
1292
1293* **term**: the term to delete from the dictionary.
1294
1295### Returns
1296
1297Returns int, specifically the number of terms that were deleted.
1298
1299---
1300
1301## FT.DICTDUMP
1302
1303### Format
1304```
1305  FT.DICTDUMP {dict}
1306```
1307
1308### Description
1309
1310Dumps all terms in the given dictionary.
1311
1312### Parameters
1313
1314* **dict**: the dictionary name.
1315
1316### Returns
1317
1318Returns an array, where each element is term (string).
1319
1320---
1321
1322## FT.CONFIG
1323
1324### Format
1325```
1326  FT.CONFIG <GET|HELP> {option}
1327  FT.CONFIG SET {option} {value}
1328```
1329
1330### Description
1331
1332Retrieves, describes and sets runtime configuration options.
1333
1334### Parameters
1335
1336* **option**: the name of the configuration option, or '*' for all.
1337* **value**: a value for the configuration option.
1338
1339For details about the configuration options refer to [Configuring](Configuring.md).
1340
1341Setting values in runtime is supported for these configuration options:
1342
1343* `NOGC`
1344* `MINPREFIX`
1345* `MAXEXPANSIONS`
1346* `TIMEOUT`
1347* `ON_TIMEOUT`
1348* `MIN_PHONETIC_TERM_LEN`
1349
1350### Returns
1351
1352When provided with a valid option name, the `GET` subcommand returns a string with the current option's value. An array containing an array for each configuration option, consisting of the option's name and current value, is returned when '*' is provided.
1353
1354The `SET` subcommand returns 'OK' for valid runtime-settable option names and values.
1355