TairSearch commands

更新时间:
复制 MD 格式

TairSearch is a full-text search module built into Tair (Redis OSS-Compatible). It uses a query syntax similar to Elasticsearch, delivering millisecond-level write and search performance.

Overview

TairSearch provides the following capabilities:

  • Low latency and high performance: Millisecond-level write and full-text search powered by the Tair in-memory engine. For details, see TairSearch performance whitepaper.

  • Incremental and partial updates: Add, update, remove, and auto-increment individual document fields without rewriting entire documents.

  • Elasticsearch-like query syntax: JSON-based Query DSL supporting bool, match, term, paging, and sorting -- familiar to developers with Elasticsearch experience.

  • Aggregation: terms, metrics, and filter aggregations for analytics on search results. See Aggregations.

  • Auto-complete: Prefix-based fuzzy matching for search-as-you-type experiences.

  • Built-in and custom analyzers: Built-in analyzers for English (standard, stop), Chinese (jieba, IK), and other languages. Custom analyzers with user-defined dictionaries and stop words are also supported. For details, see Search analyzers.

  • Shard index query: Search across multiple shard indexes with TFT.MSEARCH and get aggregated results.

  • Document compression: Compress stored documents to reduce memory usage. Disabled by default.

  • Query caching: Cache recent query results to improve hot-data query performance.

Prerequisites

The instance must be a Tair memory-optimized instance (DRAM-based) running one of these versions:

Engine version

Minimum minor version

Redis 5.0-compatible

1.7.27 or later

Redis 6.0-compatible

6.2.4.1 or later

Redis 7.0-compatible

All minor versions

Update the instance to the latest minor version for the most features and highest stability. For instructions, see Upgrade minor and proxy versions. For cluster or read/write splitting instances, also update the proxy nodes to the latest minor version to make sure all commands work as expected.

Release notes

Redis 5.0-compatible DRAM-based instances

Date

Version

Changes

2022-03-11

V1.7.27

TairSearch released

2022-05-24

V1.8.5

Aggregation feature

2022-09-06

V5.0.15

TFT.MSEARCH command

2023-01-13

V5.0.25

Analyzers

2023-03-15

V5.0.28

Query caching, document compression, TFT.ANALYZER command

2023-06-12

V5.0.35

ARRAY data type, Okapi BM25 similarity algorithm

Redis 6.0-compatible DRAM-based instances

Date

Version

Changes

2023-02-07

V6.2.4.1

TairSearch (all features of V5.0.25)

2023-03-14

V6.2.5.0

Query caching, document compression, TFT.ANALYZER (all features of V5.0.28)

2023-06-12

V6.2.7.3

ARRAY data type, Okapi BM25 (all features of V5.0.35)

2023-12-21

V23.12.1.2

TFT.EXPLAINSCORE command

Redis 7.0-compatible DRAM-based instances

Date

Version

Changes

2024-07-22

V24.7.0.0

TairSearch support

Best practices

Usage notes

  • TairSearch data is stored on the Tair instance and consumes instance memory.

  • To reduce memory usage:

    • Set index to true only for fields that need to be searchable. Set index to false for other fields.

    • Use _source with includes/excludes patterns to store only the document fields you need.

    • Choose an appropriate analyzer to avoid unnecessary tokenization and increased memory usage.

    • Enable document compression for large documents.

  • Keep the number of documents per index within 5 million. This prevents data skew in cluster instances, balances read and write requests, and reduces large keys and hotkeys. Split large datasets across multiple indexes and use TFT.MSEARCH to query them together.

Syntax conventions

Convention

Meaning

UPPERCASE

Command keyword

*italic*

Variable

[options]

Optional parameter. Parameters without brackets are required.

`A\

B`

Mutually exclusive parameters. Specify only one.

...

The preceding parameter can be repeated.


Full-text search commands

TFT.CREATEINDEX

Creates an index with a mapping definition. The mapping syntax is similar to Elasticsearch explicit mapping. An index must be created before documents can be added.

Syntax

TFT.CREATEINDEX index mappings [settings]
To prevent large keys, split large indexes into smaller indexes with identical mappings and settings, then query them together with TFT.MSEARCH.

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index to create.

*mappings*

Yes

The JSON mapping definition. See Mapping options.

*settings*

No

The JSON settings for the index. See Index settings.

Mapping options

The mappings object supports the following top-level fields:

dynamic

The mapping mode. Valid values:

  • "strict" -- Data can only be written to fields defined in properties. Writing to undefined fields fails.

  • Not specified (default) -- Non-strict mode. The system does not check whether written fields are defined in properties.

enabled

Controls type checking for non-indexed fields (index set to false). Valid values: true (default) and false. When true, a write fails if the field type does not match the type defined in properties. Indexed fields are always type-checked regardless of this setting.

_source

Controls whether the original document is stored. This setting does not affect index creation.

  • enabled -- true (default) stores the original document. false does not store it.

  • includes -- An array of field name patterns to include. Wildcards are supported.

  • excludes -- An array of field name patterns to exclude. Wildcards are supported. If a field matches both includes and excludes, excludes takes precedence (the field is not stored).

Examples:

"_source": {"enabled": true}

This is the default -- stores all fields. Equivalent to "_source": {"enabled": true, "excludes": [], "includes": []}.

"_source": {"enabled": true, "excludes": [], "includes": ["id", "name"]}

Stores only the id and name fields.

properties

A collection of field definitions. Each field supports the following attributes:

Attribute

Description

Default

type

The data type. See Field types.

Required

index

Whether this field is indexed (searchable). true or false.

true

boost

The field weight for scoring. A positive floating-point number.

1

similarity

The similarity algorithm: "classic" (TF-IDF) or "BM25" (Okapi BM25).

"classic"

Field types

Type

Description

Type-specific options

keyword

A string that is not tokenized. Suitable for exact-match queries.

ignore_above: Maximum string length. Default: 128.

text

A string that is tokenized by an analyzer before indexing.

analyzer, search_analyzer. See Text analyzer options.

long

64-bit integer. Suitable for timestamps (Unix epoch).

--

integer

32-bit integer.

--

double

64-bit floating-point number. NaN, Inf, and -Inf are not supported.

--

ARRAY support: All field types support array variants. Append [] to the type name. For example, keyword[] declares an array of keywords.

TFT.CREATEINDEX idx:products '{"mappings":{"properties":{"tags":{"type":"keyword[]"}}}}'

Text analyzer options

Option

Description

Default

analyzer

The analyzer used for indexing. See Built-in analyzers. Custom analyzers can also be specified, configured via the analysis section in settings.

"standard"

search_analyzer

The analyzer used at search time. Same valid values as analyzer.

Same as analyzer

Built-in analyzers

standard (default), jieba (recommended for Chinese, works better than chinese), stop, IK, pattern, whitespace, simple, keyword, chinese, french, dutch, russian.

For details, see Built-in analyzers.

Index settings

The optional settings object supports the following fields:

analysis

Defines custom analyzers. For details, see Custom analyzers.

index

Configures custom similarity algorithms. Use this to customize Okapi BM25 parameters:

Parameter

Description

Default

Valid values

k1

Controls how much term frequency affects the score. Higher values increase the effect.

1.2

Greater than 0

b

Controls how much document length affects the score. Higher values increase the effect.

0.75

0 to 1

Example:

TFT.CREATEINDEX idx:products '{"mappings":{"properties":{"name":{"type":"keyword","similarity":"my_bm25"}}},"settings":{"index":{"similarity":{"my_bm25":{"type":"BM25","k1":1.0,"b":1.0}}}}}'

queries_cache

Configures the query result cache. By default, the cache stores up to 10,000 results without a memory limit. When full, results are evicted using the Least Recently Used (LRU) algorithm.

Parameter

Type

Description

Default

size

STRING

Maximum memory for all query caches. Supports "bytes", "kb", and "mb" units. Examples: "1000" (1,000 bytes), "10kb", "1mb".

No limit

ttl

INTEGER

Time to Live for cached results, in seconds.

10

Example:

"settings": {"queries_cache": {"size": "100mb", "ttl": 3}}
queries_cache is a node-level parameter. Configuring it on one index affects all other indexes in the same process. Use the same queries_cache configuration across all indexes.

compress_doc

Configures transparent document compression. Enabling compression increases CPU consumption and read/write latency. Enable this only when the index is large (kilobytes or more) and storage cost is the primary concern.

Parameter

Type

Description

Default

size

STRING

Compression threshold. Documents are compressed only when they reach this size. Supports "bytes", "kb", and "mb" units.

"10kb"

enable

BOOLEAN

Whether to enable compression.

false

Example:

"settings": {"compress_doc": {"size": "1kb", "enable": true}}
Compression applies only to documents written or updated after you enable the setting with TFT.UPDATEINDEX. Existing documents are not retroactively compressed.

Return value

  • On success: OK

  • On failure: An error message

Example

TFT.CREATEINDEX idx:product '{"mappings":{"_source":{"enabled":true},"properties":{"product_id":{"type":"keyword","ignore_above":128},"product_name":{"type":"text"},"product_title":{"type":"text","analyzer":"jieba"},"price":{"type":"double"}}}}'
OK

See also: TFT.UPDATEINDEX, TFT.GETINDEX


TFT.UPDATEINDEX

Adds new fields to an index mapping or modifies index settings.

Syntax

TFT.UPDATEINDEX index mappings [settings]

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*mappings*

Yes

New properties fields to add. Only specify the fields being added -- dynamic, _source, and other top-level mapping options cannot be changed. New fields must not conflict with existing fields.

*settings*

No

Modified index settings. Only queries_cache, compress_doc, and index (BM25 k1/b values) can be modified.

For the full syntax of mappings and settings, see TFT.CREATEINDEX.

Return value

  • On success: OK

  • On failure: An error message

Example

TFT.UPDATEINDEX idx:product '{"mappings":{"properties":{"product_group":{"type":"text","analyzer":"chinese"}}}}'
OK

See also: TFT.CREATEINDEX, TFT.GETINDEX


TFT.GETINDEX

Retrieves the mapping and settings of an index.

Syntax

TFT.GETINDEX index

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

Return value

  • On success: The JSON-formatted mapping content of the index

  • On failure: An error message

Example

TFT.GETINDEX idx:product
{"idx:product0310":{"mappings":{"_source":{"enabled":true,"excludes":[],"includes":["product_id"]},"dynamic":"false","properties":{"price":{"boost":1.0,"enabled":true,"ignore_above":-1,"index":true,"similarity":"classic","type":"double"},"product_id":{"boost":1.0,"enabled":true,"ignore_above":128,"index":true,"similarity":"classic","type":"keyword"},"product_name":{"boost":1.0,"enabled":true,"ignore_above":-1,"index":true,"similarity":"classic","type":"text"},"product_title":{"analyzer":"chinese","boost":1.0,"enabled":true,"ignore_above":-1,"index":true,"similarity":"classic","type":"text"}}}}}

See also: TFT.CREATEINDEX, TFT.UPDATEINDEX


TFT.ADDDOC

Adds a single document to an index.

Syntax

TFT.ADDDOC index document [WITH_ID doc_id]

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*document*

Yes

The JSON document. Field values must match the data types defined in the mapping.

WITH_ID *doc_id*

No

A custom document ID (string). If omitted, an ID is auto-generated. If the specified ID already exists, the existing document is overwritten.

If _source is configured with includes, only the fields listed in includes are stored when adding or updating a document.

Return value

  • On success: A JSON object containing the document ID, e.g., {"_id":"00001"}

  • On failure: An error message

Examples

Add a document with a custom ID:

TFT.ADDDOC idx:product '{"product_id":"product test"}' WITH_ID 00001
{"_id":"00001"}

Add a document with an array field:

TFT.ADDDOC idx:product '{"product_id":["an","2","3df"]}' WITH_ID 00001

See also: TFT.MADDDOC, TFT.UPDATEDOCFIELD, TFT.DELDOC


TFT.MADDDOC

Adds multiple documents to an index in a single atomic operation. If any document has an invalid format, none of the documents are added.

Syntax

TFT.MADDDOC index document doc_id [document1 doc_id1] ...

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*document*

Yes

A JSON document. Field values must match the data types defined in the mapping.

*doc_id*

Yes

The document ID (string).

If _source is configured with includes, only the fields listed in includes are stored when adding or updating a document.

Return value

  • On success: OK

  • On failure: An error message

Example

TFT.MADDDOC idx:product '{"product_id":"test1"}' 00011 '{"product_id":"test2"}' 00012
OK

See also: TFT.ADDDOC, TFT.DELDOC


TFT.UPDATEDOCFIELD

Updates specific fields in a document. If the document does not exist, it is created (equivalent to TFT.ADDDOC). If a field does not exist, it is added.

Syntax

TFT.UPDATEDOCFIELD index doc_id document

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*doc_id*

Yes

The ID of the document to update.

*document*

Yes

A JSON object containing the fields to update. Indexed fields must match the data types defined in the mapping. Non-indexed fields can be of any type.

If _source is configured with includes, only the fields listed in includes are stored when adding or updating a document.

Return value

  • On success: OK

  • On failure: An error message

Example

TFT.UPDATEDOCFIELD idx:product 00011 '{"product_id":"test8","product_group":"BOOK"}'
OK

See also: TFT.ADDDOC, TFT.DELDOCFIELD


TFT.DELDOCFIELD

Deletes one or more fields from a document. If the field is indexed, its index entry is also removed.

Syntax

TFT.DELDOCFIELD index doc_id field [field1 field2 ...]

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*doc_id*

Yes

The ID of the document.

*field*

Yes

One or more field names to delete.

The operation fails if the specified field does not exist in the document (for example, a field filtered out by _source).

Return value

  • On success: The number of deleted fields (integer)

  • On failure: An error message

Example

TFT.DELDOCFIELD idx:product 00011 product_group
(integer) 1

See also: TFT.UPDATEDOCFIELD


TFT.INCRLONGDOCFIELD

Increments an integer field in a document. The field must be of type LONG or INTEGER. The ARRAY data type is not supported.

Syntax

TFT.INCRLONGDOCFIELD index doc_id field increment

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*doc_id*

Yes

The ID of the document.

*field*

Yes

The field to increment. Must be LONG or INTEGER type.

*increment*

Yes

The increment value. Can be a positive or negative integer.

If the document does not exist, it is auto-created with the field initialized to 0 before applying the increment. The operation fails if the field does not exist in the document (for example, a field filtered out by _source).

Return value

  • On success: The updated field value (integer)

  • On failure: An error message

Example

TFT.INCRLONGDOCFIELD idx:product 00011 stock 100
(integer)100

See also: TFT.INCRFLOATDOCFIELD, TFT.UPDATEDOCFIELD


TFT.INCRFLOATDOCFIELD

Increments a floating-point field in a document. The field must be of type DOUBLE. The ARRAY data type is not supported.

Syntax

TFT.INCRFLOATDOCFIELD index doc_id field increment

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*doc_id*

Yes

The ID of the document.

*field*

Yes

The field to increment. Must be DOUBLE type.

*increment*

Yes

The increment value. Can be a positive or negative floating-point number.

If the document does not exist, it is auto-created with the field initialized to 0 before applying the increment. The operation fails if the field does not exist in the document (for example, a field filtered out by _source).

Return value

  • On success: The updated field value (string)

  • On failure: An error message

Example

TFT.INCRFLOATDOCFIELD idx:product 00011 stock 299.6
"299.6"

See also: TFT.INCRLONGDOCFIELD, TFT.UPDATEDOCFIELD


TFT.GETDOC

Retrieves a document by its ID.

Syntax

TFT.GETDOC index doc_id

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*doc_id*

Yes

The ID of the document.

Return value

  • On success: A JSON object with the document ID and content

  • On failure: An error message

Example

TFT.GETDOC idx:product 00011
{"_id":"00011","_source":{"product_id":"test8"}}

See also: TFT.EXISTS, TFT.SEARCH


TFT.EXISTS

Checks whether a document exists in an index.

Syntax

TFT.EXISTS index doc_id

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*doc_id*

Yes

The ID of the document.

Return value

  • 1 if the document exists

  • 0 if the index or document does not exist

  • On failure: An error message

Example

TFT.EXISTS idx:product 00011
(integer) 1

See also: TFT.GETDOC, TFT.DOCNUM


TFT.DOCNUM

Gets the number of documents in an index.

Syntax

TFT.DOCNUM index

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

Return value

  • On success: The document count (integer)

  • On failure: An error message

Example

TFT.DOCNUM idx:product
(integer) 3

See also: TFT.EXISTS, TFT.SCANDOCID


TFT.SCANDOCID

Scans document IDs in an index using a cursor, similar to the Redis SCAN command.

Syntax

TFT.SCANDOCID index cursor [MATCH *value*] [COUNT count]

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*cursor*

Yes

The cursor position. Use 0 to start a new scan.

MATCH *\*value\**

No

A glob-style pattern to filter document IDs. Example: MATCH *redis*.

COUNT *count*

No

The maximum number of items to return per scan. Default: 100.

Return value

A two-element array:

  1. The cursor for the next iteration. 0 indicates the scan is complete.

  2. An array of document IDs.

Example

TFT.SCANDOCID idx:product 0 COUNT 3
1) "0"
2) 1) "00001"
   2) "00011"
   3) "00012"

See also: TFT.DOCNUM, TFT.GETDOC


TFT.DELDOC

Deletes one or more documents from an index by document ID.

Syntax

TFT.DELDOC index doc_id [doc_id] ...

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*doc_id*

Yes

One or more document IDs to delete.

Return value

  • On success: The number of documents actually deleted (string). Non-existent IDs are ignored.

  • On failure: An error message

Example

TFT.DELDOC idx:product 00011 00014
"1"    # Document 00014 does not exist, so only document 00011 is deleted.

See also: TFT.DELALL, TFT.ADDDOC


TFT.DELALL

Deletes all documents from an index while retaining the index and its mapping.

Syntax

TFT.DELALL index

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

Return value

  • On success: OK

  • On failure: An error message

Example

TFT.DELALL idx:product
OK

See also: TFT.DELDOC, DEL


TFT.ANALYZER

Tests how an analyzer tokenizes a given text.

Syntax

TFT.ANALYZER analyzer_name text [INDEX index_name] [SHOW_TIME]

Parameters

Parameter

Required

Description

*analyzer_name*

Yes

The name of a built-in or custom analyzer.

*text*

Yes

The text to tokenize. Must be UTF-8 encoded.

INDEX *index_name*

Conditional

The index containing the analyzer definition. Required when using a custom analyzer or a built-in analyzer with modified stop words or dictionaries.

SHOW_TIME

No

Include tokenization duration in the output, in microseconds. The first run with a large dictionary (e.g., Jieba, IK) may take several seconds due to dictionary loading.

Return value

  • On success: A JSON object containing token details

  • On failure: An error message

Example

TFT.ANALYZER standard "Tair is a nosql database"
{
    "tokens": [
        {"token": "Tair", "start_offset": 0, "end_offset": 4, "position": 0},
        {"token": "nosql", "start_offset": 10, "end_offset": 15, "position": 3},
        {"token": "database", "start_offset": 16, "end_offset": 24, "position": 4}
    ]
}

DEL (native Redis)

Use the native Redis DEL command to delete one or more TairSearch keys (indexes).

DEL key [key ...]

For details, see the DEL command reference.


TFT.SEARCH

Searches for documents in an index using the Query DSL.

Syntax

TFT.SEARCH index query

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*query*

Yes

A JSON Query DSL statement. See sections below for the full syntax.

The query syntax is similar to Elasticsearch Query DSL.

Return value

On success, a JSON object containing search results:

{
    "hits": {
        "hits": [
            {"_id": "...", "_index": "...", "_score": 1.0, "_source": {...}}
        ],
        "max_score": 1.0,
        "total": {
            "relation": "eq",
            "value": 3
        }
    }
}

The total.relation field indicates how the count relates to total.value:

  • "eq" -- The count is exact.

  • "gte" -- The count is at least this value (when track_total_hits is false).

Example

TFT.SEARCH idx:product '{"sort":[{"price":{"order":"desc"}}]}'
{"hits":{"hits":[{"_id":"fruits_3","_index":"idx:product","_score":1.0,"_source":{"product_id":"fruits_3","product_name":"orange","price":30.2,"stock":3000}},{"_id":"fruits_2","_index":"idx:product","_score":1.0,"_source":{"product_id":"fruits_2","product_name":"banana","price":24.0,"stock":2000}},{"_id":"fruits_1","_index":"idx:product","_score":1.0,"_source":{"product_id":"fruits_1","product_name":"apple","price":19.5,"stock":1000}}],"max_score":1.0,"total":{"relation":"eq","value":3}}}

See also: TFT.MSEARCH, TFT.EXPLAINCOST, TFT.EXPLAINSCORE


Query types

The query field in the Query DSL supports the following query types.

match

Full-text match query. The query text is tokenized and matched against the index. For exact-match or prefix scenarios that do not require tokenization or fuzzy matching, use term or prefix instead for better performance.

Parameter

Type

Description

Default

query

STRING

The search text. When fuzzy match is disabled, the text is tokenized using the specified analyzer, and you can control token matching with operator and minimum_should_match. When fuzzy match is enabled (fuzziness), these parameters are ignored.

Required

analyzer

STRING

The analyzer to use. Valid values: standard (default), chinese, arabic, cjk, czech, brazilian, german, greek, persian, french, dutch, russian, jieba. See Search analyzers.

"standard"

operator

STRING

The relationship between tokens. "OR" matches documents containing any token. "AND" matches documents containing all tokens.

"OR"

minimum_should_match

INTEGER

Minimum number of tokens that must match. Effective when fuzzy match is disabled and operator is "OR".

--

fuzziness

INTEGER

Enable fuzzy match. Set to 1 to enable. When enabled, operator and minimum_should_match are ignored.

Disabled

prefix_length

INTEGER

Number of leading characters that must match exactly in fuzzy mode.

0

Example -- basic match:

{"query": {"match": {"f0": {"query": "redis cluster", "operator": "OR"}}}}

Example -- fuzzy match:

{"query": {"match": {"f0": {"query": "excelentl", "fuzziness": 1}}}}
term

Exact token query without tokenization. More efficient than match for exact lookups. Supports all field types.

Parameter

Type

Description

Default

value

STRING

The exact value to match.

Required

boost

DOUBLE

Score weight for this query clause.

1.0

lowercase

BOOLEAN

Convert the query value to lowercase before matching. Set to false if the indexed document was not lowercased by its analyzer.

true

Examples:

{"query": {"term": {"f0": {"value": "redis", "boost": 2.0}}}}
{"query": {"term": {"f0": {"value": "redis", "lowercase": false}}}}
terms

Multi-value exact query. Matches documents containing any of the specified values. Maximum 1,024 values per query.

Parameter

Type

Description

Default

lowercase

BOOLEAN

Convert query values to lowercase before matching.

true

Example:

{"query": {"terms": {"f0": ["redis", "excellent"]}}}
If the analyzer used for indexing does not lowercase the text, set lowercase to false to avoid missed matches.
range

Range query. Supports all field types.

Operator

Meaning

lt

Less than

gt

Greater than

lte

Less than or equal to

gte

Greater than or equal to

Example:

{"query": {"range": {"f0": {"lt": "abcd", "gt": "ab"}}}}
wildcard

Wildcard pattern query. Supported wildcards: * (matches any character sequence) and ? (matches a single character).

Example:

{"query": {"wildcard": {"f0": {"value": "*b?Se"}}}}
prefix

Prefix query. Matches documents where the field value starts with the specified string.

Example:

{"query": {"prefix": {"f0": "abcd"}}}
bool

Compound query combining multiple query clauses. Maximum 1,024 clauses per bool query. Nested bool queries are supported.

Clause

Description

must

Results must match all clauses in this list.

must_not

Results must not match any clause in this list.

should

Results should match at least minimum_should_match clauses.

minimum_should_match

Minimum number of should clauses that must match. Defaults to 1 when only should is present, 0 when must or must_not is also present.

Example -- must:

{"query": {"bool": {"must": [{"match": {"DB": "redis"}}, {"match": {"Architectures": "cluster"}}]}}}

Example -- should with minimum_should_match:

{"query": {"bool": {"minimum_should_match": 1, "should": [{"match": {"DB": "redis"}}, {"match": {"Architectures": "cluster"}}]}}}

Example -- nested bool:

TFT.SEARCH idx:product '{"query":{"bool":{"must":[{"term":{"product_name":"apple"}},{"bool":{"minimum_should_match":1,"should":[{"term":{"price":19.5}},{"term":{"product_id":"fruits_2"}}]}}]}}}'
dis_max

Best-match compound query. Returns documents matching one or more clauses and assigns the highest individual clause score.

Parameter

Type

Description

Default

queries

ARRAY

An array of query clauses.

Required

tie_breaker

DOUBLE

A multiplier (0 to 1) applied to scores from non-best-matching clauses. Final score = best clause score + (sum of other clause scores x tie_breaker).

0

Example: With three clauses scoring 5, 1, and 3 for a document and tie_breaker of 0.5, the final score is 5 + ((1 + 3) x 0.5) = 7.

{"query": {"dis_max": {"queries": [{"term": {"f0": "redis"}}, {"term": {"f1": "database"}}, {"match": {"title": "redis memory database"}}], "tie_breaker": 0.5}}}
constant_score

Wraps another query and returns a constant score for all matching documents.

Parameter

Type

Description

Default

filter

OBJECT

The query to wrap.

Required

boost

DOUBLE

The constant score to assign.

1.0

Example:

{"query": {"constant_score": {"filter": {"term": {"f0": "abc"}}, "boost": 1.2}}}
match_all

Matches all documents in the index with a uniform score.

Parameter

Type

Description

Default

boost

DOUBLE

The score to assign to all documents.

1.0

Example:

{"query": {"match_all": {"boost": 2.3}}}
In compound queries (bool, dis_max, constant_score), you can set boost values on term, terms, range, and wildcard clauses to control scoring weight. The default boost is 1. Specify the boost inside the parameter syntax, for example: {"term": {"f0": {"value": "redis", "boost": 2}}}.

Sorting

Use the sort field to control result ordering. The ARRAY data type is not supported for sorting.

Value

Description

"_score"

Sort by relevance score in descending order.

"_doc"

Sort by document ID in ascending order.

*field_name*

Sort by a specific field in ascending order. The field must be indexed (index: true) or type-checked (enabled: true) and of type keyword, long, integer, or double.

For multi-field sorting, use an array. Control sort direction with order ("desc" or "asc"):

{"sort": [{"price": {"order": "desc"}}, {"_doc": {"order": "desc"}}]}

Source filtering

Use the _source field to control which document fields appear in results:

{"_source": {"includes": ["f0"]}}

Supports both includes and excludes with wildcard patterns.

Paging

Parameter

Type

Description

Default

from

INTEGER

The zero-based offset of the first result to return.

0

size

INTEGER

The maximum number of results to return. Valid values: 0 to 10000. A value of 0 returns only the total count without documents.

10

Using from and size together provides paging. Query performance decreases as from increases.

track_total_hits

Controls whether to count all matching documents for term, terms, or match queries (compound queries are also supported, but fuzzy match within match is disabled).

Value

Behavior

false

Returns only the top 100 documents sorted by score.

true

Counts all matching documents.

Warning

Setting track_total_hits to true with a large number of matching documents can cause slow queries. Use with caution.


TFT.MSEARCH

Searches across multiple indexes that share identical mappings and settings, then aggregates and returns the combined results.

Syntax

TFT.MSEARCH index_count index [index1] ... query

Parameters

Parameter

Required

Description

*index_count*

Yes

The number of indexes to search. Valid values: 1 to 100.

*index*

Yes

One or more index names. All indexes must have identical mappings and settings. An error is returned if mappings differ or an index does not exist.

*query*

Yes

A JSON Query DSL statement. Supports query, sort, _source, aggs, track_total_hits, size, reply_with_keys_cursor, and keys_cursor.

TFT.MSEARCH does not support the from parameter. Use cursor-based paging instead (see below).

Cursor-based paging

Use size, reply_with_keys_cursor, and keys_cursor together for paging:

Parameter

Type

Description

Default

size

INTEGER

Number of results to return per page.

10

reply_with_keys_cursor

BOOLEAN

Include cursor positions in the response.

false

keys_cursor

OBJECT

Cursor positions from the previous query. Use 0 (or omit) for the first query.

0

How it works:

  1. First query: Set reply_with_keys_cursor to true and omit keys_cursor (or set to 0). Tair retrieves size documents from each index, then gathers, scores, sorts, and aggregates the combined results, returning the top size documents. The response includes keys_cursor positions for each index.

  2. Next query: Pass the returned keys_cursor from the previous response. Tair continues retrieval from the cursor positions in each index.

Aggregation behavior

TFT.MSEARCH aggregates child result sets from each index rather than aggregating the combined dataset:

  • Rate and sort: Scores and sorts child result sets.

  • sum, max, min, avg, value_count: Aggregates across child result sets.

  • sum_of_squares, variance, std_deviation: Averages across child result sets.

  • Terms aggregation and filter aggregation: Aggregates across child result sets separately.

Return value

On success, a JSON object similar to TFT.SEARCH output, plus an aux_info field:

{
    "aux_info": {
        "index_crc64": 15096806844241479487,
        "keys_cursor": {"key0": 2, "key1": 5, "key2": 3},
        "field_type": {"f0": "long"}
    }
}

Field

Description

index_crc64

CRC-64 hash of the mappings and settings. Can be ignored for business requests.

keys_cursor

Cursor positions for the next paged query. Included only when reply_with_keys_cursor is true.

field_type

Data types of sorted fields. Included only when sorting by an index field.

Example

Set up three indexes with the same mapping:

TFT.CREATEINDEX key0 '{"mappings":{"properties":{"f0":{"type":"long"}}}}'
TFT.CREATEINDEX key1 '{"mappings":{"properties":{"f0":{"type":"long"}}}}'
TFT.CREATEINDEX key2 '{"mappings":{"properties":{"f0":{"type":"long"}}}}'
TFT.ADDDOC key0 '{"f0":120}'
TFT.ADDDOC key0 '{"f0":130}'
TFT.ADDDOC key1 '{"f0":140}'
TFT.ADDDOC key1 '{"f0":150}'
TFT.ADDDOC key2 '{"f0":160}'
TFT.ADDDOC key2 '{"f0":170}'

First page:

TFT.MSEARCH 3 key0 key1 key2 '{"size":2,"query":{"range":{"f0":{"gt":120,"lte":170}}},"sort":[{"f0":{"order":"desc"}}],"reply_with_keys_cursor":true}'
{"hits":{"hits":[{"_id":"16625439765504840","_index":"key2","_score":1.0,"_source":{"f0":170}},{"_id":"16625439741096630","_index":"key2","_score":1.0,"_source":{"f0":160}}],"max_score":1.0,"total":{"relation":"eq","value":5}},"aux_info":{"index_crc64":10084399559244916810,"keys_cursor":{"key0":0,"key1":0,"key2":2}}}

Second page (pass the keys_cursor from the previous response):

TFT.MSEARCH 3 key0 key1 key2 '{"size":2,"query":{"range":{"f0":{"gt":120,"lte":170}}},"sort":[{"f0":{"order":"desc"}}],"reply_with_keys_cursor":true,"keys_cursor":{"key0":0,"key1":0,"key2":2}}'
{"hits":{"hits":[{"_id":"16625439652681160","_index":"key1","_score":1.0,"_source":{"f0":150}},{"_id":"16625439624704580","_index":"key1","_score":1.0,"_source":{"f0":140}}],"max_score":1.0,"total":{"relation":"eq","value":5}},"aux_info":{"index_crc64":10084399559244916810,"keys_cursor":{"key0":0,"key1":2,"key2":2}}}

See also: TFT.SEARCH


TFT.EXPLAINCOST

Retrieves the execution time breakdown of a query.

Syntax

TFT.EXPLAINCOST index query

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*query*

Yes

A Query DSL statement (same syntax as TFT.SEARCH).

Return value

A JSON object with the following sections:

Section

Description

QUERY_COST

Query execution time in microseconds (time_cost_us), plus the query view (query) and document count (doc_num). For bool queries, includes per-step timing (steps).

AGGS_COST

Aggregation time in microseconds. Omitted if no aggregation is specified.

COLLECTOR_COST

Time for collecting and sorting results in microseconds, plus the collector type: ScoreCollector (score-based) or CustomSortCollector (field-based).

Example

TFT.EXPLAINCOST idx:product '{"sort":[{"price":{"order":"desc"}}]}'
{
    "QUERY_COST": {
        "query": "MATCHALL_QUERY",
        "doc_num": 1,
        "time_cost_us": 2
    },
    "COLLECTOR_COST": {
        "collector_type": "CustomSortCollector",
        "time_cost_us": 20
    }
}

See also: TFT.SEARCH, TFT.EXPLAINSCORE


TFT.EXPLAINSCORE

Retrieves detailed scoring breakdowns for search results, showing how document scores are calculated.

Available only for DRAM-based instances compatible with Redis 6.0 or later.

Syntax

TFT.EXPLAINSCORE index query [doc_id] ...

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*query*

Yes

A Query DSL statement (same syntax as TFT.SEARCH).

*doc_id*

No

One or more document IDs. When specified, only these documents are included in the output.

Return value

The same result set as TFT.SEARCH, plus an _explanation object for each document containing:

Field

Description

score

The document score.

description

The formula used for score calculation.

field

The document field matching the query terms.

term

The query term found in the document.

query_boost

The scoring weight applied to this query clause.

details

Metadata and the step-by-step scoring process.

Example

TFT.EXPLAINSCORE today_shares '{"query":{"wildcard":{"shares_name":{"value":"*BY"}}}}'
{
    "hits": {
        "hits": [
            {
                "_id": "17036492095306830",
                "_index": "today_shares",
                "_score": 1.0,
                "_source": {
                    "shares_name": "YBY",
                    "logictime": 14300410,
                    "purchase_type": 1,
                    "purchase_price": 11.1,
                    "purchase_count": 100,
                    "investor": "Mila"
                },
                "_explanation": {
                    "score": 1.0,
                    "description": "score, computed as query_boost",
                    "field": "shares_name",
                    "term": "*BY",
                    "query_boost": 1.0
                }
            }
        ],
        "max_score": 1.0,
        "total": {"relation": "eq", "value": 1}
    }
}

See also: TFT.SEARCH, TFT.EXPLAINCOST


Auto-complete commands

TFT.ADDSUG

Adds one or more auto-complete text entries with associated weights.

Syntax

TFT.ADDSUG index text weight [text weight] ...

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*text*

Yes

The auto-complete text entry.

*weight*

Yes

The scoring weight (positive integer). Higher weights rank higher in results.

Return value

  • On success: The number of added text entries (integer)

  • On failure: An error message

Example

TFT.ADDSUG idx:redis 'redis is a memory database' 3 'redis cluster' 10
(integer) 2

See also: TFT.GETSUG, TFT.DELSUG, TFT.SUGNUM


TFT.DELSUG

Deletes one or more auto-complete text entries from an index.

Syntax

TFT.DELSUG index text [text] ...

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*text*

Yes

The exact text entry to delete. Must be a complete and exact match.

Return value

  • On success: The number of deleted text entries (integer)

  • On failure: An error message

Example

TFT.DELSUG idx:redis 'redis is a memory database' 'redis cluster'
(integer) 2

See also: TFT.ADDSUG, TFT.SUGNUM


TFT.SUGNUM

Gets the number of auto-complete text entries in an index.

Syntax

TFT.SUGNUM index

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

Return value

  • On success: The entry count (integer)

  • On failure: An error message

Example

TFT.SUGNUM idx:redis
(integer) 3

See also: TFT.ADDSUG, TFT.GETSUG


TFT.GETSUG

Retrieves auto-complete suggestions matching a prefix. Results are returned in descending order of weight.

Syntax

TFT.GETSUG index prefix [MAX_COUNT count] [FUZZY]

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

*prefix*

Yes

The prefix to match.

MAX_COUNT *count*

No

Maximum number of entries to return. Valid values: 0 to 255.

FUZZY

No

Enable fuzzy matching.

Return value

  • On success: A list of matching auto-complete text entries

  • On failure: An error message

Example

TFT.GETSUG idx:redis res MAX_COUNT 2 FUZZY
1) "redis cluster"
2) "redis lock"

See also: TFT.ADDSUG, TFT.GETALLSUGS


TFT.GETALLSUGS

Retrieves all auto-complete text entries in an index.

Syntax

TFT.GETALLSUGS index

Parameters

Parameter

Required

Description

*index*

Yes

The name of the index.

Return value

  • On success: A list of all auto-complete text entries

  • On failure: An error message

Example

TFT.GETALLSUGS idx:redis
1) "redis cluster"
2) "redis lock"
3) "redis is a memory database"

See also: TFT.GETSUG, TFT.ADDSUG


Aggregations

Add an aggs (or aggregations) clause to a TFT.SEARCH query to perform aggregations on the result set.

Basic usage

Specify a custom aggregation name, an aggregation type, and a field to aggregate on:

TFT.SEARCH shares '{"query":{"term":{"investor":"Jay"}},"aggs":{"Jay_Sum":{"sum":{"field":"purchase_price"}}}}'

The response includes both the search results from query and the aggregation results from aggs:

{"hits":{"hits":[{"_id":"16581351808123930","_index":"today_shares0718","_score":1.0,"_source":{"shares_name":"XAX","logictime":14300210,"purchase_type":1,"purchase_price":101.1,"purchase_count":100,"investor":"Jay"}},{"_id":"16581351809626430","_index":"today_shares0718","_score":1.0,"_source":{"shares_name":"XAX","logictime":14300310,"purchase_type":1,"purchase_price":111.1,"purchase_count":100,"investor":"Jay"}}],"max_score":1.0,"total":{"relation":"eq","value":2}},"aggregations":{"Jay_Sum":{"value":212.2}}}
Add "size": 0 to the query to return only aggregation results without documents.

Metrics aggregation

Metrics aggregations perform numerical calculations on numeric fields (integer, double, etc.) and do not support nested sub-aggregations.

Metric

Description

Supported field types

sum

Sum of field values

Numeric

max

Maximum value

Numeric

min

Minimum value

Numeric

avg

Average value

Numeric

sum_of_squares

Sum of squared values

Numeric

variance

Statistical variance

Numeric

std_deviation

Standard deviation

Numeric

value_count

Count of values (without deduplication)

Numeric, keyword

extended_stats

All of the above metrics in a single response

Numeric

Only value_count supports keyword fields. All other metrics require numeric fields.

Output: A DOUBLE value computed from the specified field.

Terms aggregation

Counts deduplicated values in a keyword field. Supports nested sub-aggregations.

Parameter

Description

Default

field

The aggregation field. Only keyword fields are supported.

Required

size

Number of buckets to return. Valid values: 1 to 65535.

10

order

Sort order. {"_count": "desc"} sorts by document count (default). {"_key": "asc"} sorts alphabetically by field value.

{"_count": "desc"}

min_doc_count

Minimum document count for a bucket to be included in the results.

1

include

A regex pattern or exact value that bucket keys must match. For string fields, regex matching is supported. For array fields, exact matching is required.

--

exclude

A regex pattern or exact value that bucket keys must not match. If both include and exclude are specified, include is checked first, then exclude.

--

Output: A JSON object with buckets. Each bucket contains key (the field value) and doc_count (the document count):

{
    "aggregations": {
        "Per_Investor_Freq": {
            "buckets": [
                {"doc_count": 2, "key": "Jay"},
                {"doc_count": 1, "key": "Mila"}
            ]
        }
    }
}

Example:

{"aggs": {"Per_Investor_Freq": {"terms": {"field": "investor"}}}}

Filter aggregation

Filters query results with a query statement and counts matching documents. Supports nested sub-aggregations.

Output: The number of documents (doc_count) matching the filter condition.

Aggregation examples

The following examples use a stock trading dataset.

Step 1: Create the index

TFT.CREATEINDEX today_shares '{"mappings":{"properties":{"shares_name":{"type":"keyword"},"logictime":{"type":"long"},"purchase_type":{"type":"integer"},"purchase_price":{"type":"double"},"purchase_count":{"type":"long"},"investor":{"type":"keyword"}}}}'

Step 2: Add documents

TFT.ADDDOC today_shares '{"shares_name":"XAX","logictime":14300210,"purchase_type":1,"purchase_price":101.1,"purchase_count":100,"investor":"Jay"}'
TFT.ADDDOC today_shares '{"shares_name":"XAX","logictime":14300310,"purchase_type":1,"purchase_price":111.1,"purchase_count":100,"investor":"Jay"}'
TFT.ADDDOC today_shares '{"shares_name":"YBY","logictime":14300410,"purchase_type":1,"purchase_price":11.1,"purchase_count":100,"investor":"Mila"}'

Step 3: Run queries

sum -- Total purchase amount for an investor

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"investor":"Jay"}},"aggs":{"Jay_Sum":{"sum":{"field":"purchase_price"}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":2}},"aggregations":{"Jay_Sum":{"value":212.2}}}

max -- Highest purchase price for an investor

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"investor":"Jay"}},"aggs":{"Jay_Max":{"max":{"field":"purchase_price"}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":2}},"aggregations":{"Jay_Max":{"value":111.1}}}

avg -- Average purchase price for an investor

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"investor":"Jay"}},"aggs":{"Jay_Avg":{"avg":{"field":"purchase_price"}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":2}},"aggregations":{"Jay_Avg":{"value":106.1}}}

std_deviation -- Standard deviation of purchase prices

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"investor":"Jay"}},"aggs":{"Jay_Std_Deviation":{"std_deviation":{"field":"purchase_price"}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":2}},"aggregations":{"Jay_Std_Deviation":{"value":5.0}}}

extended_stats -- All statistics at once

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"investor":"Jay"}},"aggs":{"Jay_Extended_Stats":{"extended_stats":{"field":"purchase_price"}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":2}},"aggregations":{"Jay_Extended_Stats":{"count":2,"sum":212.2,"max":111.1,"min":101.1,"avg":106.1,"sum_of_squares":10221.21,"variance":25.0,"std_deviation":5.0}}}

terms -- Investors with at least two transactions

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"purchase_type":1}},"aggs":{"Per_Investor_Freq":{"terms":{"field":"investor","min_doc_count":2,"order":{"_key":"desc"}}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":3}},"aggregations":{"Per_Investor_Freq":{"buckets":[{"key":"Jay","doc_count":2}]}}}

Nested terms aggregation -- Per-stock transaction count with average price

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"purchase_type":1}},"aggs":{"Per_Investor_Freq":{"terms":{"field":"shares_name","include":"[A-Z]+","exclude":["XAX"]},"aggs":{"Price_Avg":{"avg":{"field":"purchase_price"}}}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":3}},"aggregations":{"Per_Investor_Freq":{"buckets":[{"key":"YBY","doc_count":1,"Price_Avg":{"value":11.1}}]}}}

Nested filter aggregation -- Filter by investor with extended stats

TFT.SEARCH today_shares '{"size":0,"query":{"term":{"purchase_type":1}},"aggs":{"Jay_BuyIn_Filter":{"filter":{"term":{"investor":"Jay"}},"aggs":{"Jay_BuyIn_Quatation":{"extended_stats":{"field":"purchase_price"}}}}}}'
{"hits":{"hits":[],"max_score":null,"total":{"relation":"eq","value":3}},"aggregations":{"Jay_BuyIn_Filter":{"doc_count":2,"Jay_BuyIn_Quatation":{"count":2,"sum":212.2,"max":111.1,"min":101.1,"avg":106.1,"sum_of_squares":10221.21,"variance":25.0,"std_deviation":5.0}}}}