

# Getting started with Vector Search
<a name="vector-search"></a>

Amazon ElastiCache for Valkey supports vector search, delivering latency as low as microseconds-the lowest latency vector search with the highest throughput and best price-performance at 95%\$1 recall rate among popular vector databases on AWS. ElastiCache for Valkey provides capabilities to index, search, and update billions of high-dimensional vector embeddings from popular providers like Amazon Bedrock, Amazon SageMaker, Anthropic or OpenAI for fast search and retrieval with up to 99% recall. Vector search for Amazon ElastiCache is ideal for use cases where peak performance and scalability are the most important selection criteria. This includes semantic caching, retrieval-augmented generation, real-time recommendations, personalization, and anomaly detection. 

Vector search can be used in conjunction with other ElastiCache features to enhance your applications. Vector search for ElastiCache is available in Valkey version 8.2 on node-based clusters in all [AWS Regions](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/) at no additional cost. To get started, create a new Valkey 8.2 cluster using the [AWS Management Console](https://console.aws.amazon.com/elasticache/), AWS SDK, or AWS CLI. You can also use vector search on your existing cluster by upgrading from any previous version of Valkey or Redis OSS to Valkey 8.2 in a [few clicks with no downtime](VersionManagement.HowTo.md).

# Vector Search Overview
<a name="vector-search-overview"></a>

Amazon ElastiCache for Valkey supports vector search, enabling you to store, search, and update billions of high-dimensional vector embeddings in-memory with latencies as low as microseconds with recall up to 99%. Vector search allows you to create, maintain and use secondary indexes for efficient and scalable search. Each vector search operation applies to a single index. Index operations apply only to the specified index. Any number of operations may be issued against any index at any time with the exception of index creation and deletion operations. At the cluster level, multiple operations against multiple indexes may be in progress simultaneously.

Within this document the terms key, row, and record are identical and used interchangeably. Similarly, the terms column, field, path and member are also used interchangeably.

The `FT.CREATE` command can be used to create an index for a subset of keys with the specified index types. `FT.SEARCH` performs queries on indexes created, and `FT.DROPINDEX` removes an existing index and all associated data. There are no special commands to add, delete or modify indexed data. The existing `HASH` or `JSON` commands that modify a key that is in an index automatically update the index.

**Topics**
+ [Indexes and the Valkey OSS keyspace](#indexes-keyspace)
+ [Index field types](#index-field-types)
+ [Vector index algorithms](#vector-index-algorithms)
+ [Vector search security](#vector-search-security)

## Indexes and the Valkey OSS keyspace
<a name="indexes-keyspace"></a>

Indexes are constructed and maintained over a subset of the Valkey OSS keyspace. The keyspace for each index is defined by a list of key prefixes that are provided when the index is created. The list of prefixes is optional and if omitted, the entire keyspace will be part of that index. Multiple indexes may choose disjoint or overlapping subsets of the keyspace without limitation.

Indexes are also typed in that they only cover keys that have a matching type. Currently, indexes are supported only on `JSON` and `HASH` types. A `HASH` index only indexes `HASH` keys covered by its prefix list and similarly a `JSON` index only indexes `JSON` keys that are covered by its prefix list. Keys within an index's keyspace prefix list that do not have the designated type are ignored and do not affect search operations.

An index is updated when a command modifies any key that is within the keyspace of the index. Valkey automatically extracts the declared fields for each index and updates the index with the new value. The update process has three steps. In the first step, the HASH or JSON key is modified and the requesting client is blocked. The second step is performed in the background and updates each of the indexes that contain the modified key. In the third step, the client is unblocked. Thus for query operations performed on the same connection as a mutation, that change is immediately visible in the search results. 

The creation of an index is a multi-step process. The first step is to execute the FT.CREATE command which defines the index. Successful execution of a create automatically initiates the second step – backfilling. The backfill process runs in a background thread and scans the key space for keys that are within the new index’s prefix list. Each key that is found is added to the index. Eventually the entire keyspace is scanned, completing the index creation process. Note that while the backfill process is running, mutations of indexed keys are permitted, there is no restriction, and the index backfill process will not complete until all keys are properly indexed. Query operations attempted while an index is undergoing backfill are not allowed and are terminated with an error. The FT.INFO command returns the backfill process status in the 'backfill\$1status' field.

## Index field types
<a name="index-field-types"></a>

Each index has a specific type that is declared when the index is created along with the location of a field (column) to be indexed. For `HASH` keys the location is the field name within the `HASH`. For `JSON` keys the location is a JSON path description. When a key is modified the data associated with the declared fields is extracted, converted to the declared type and stored in the index. If the data is missing or cannot be successfully converted to the declared type, then that field is omitted from the index. There are three types of fields, as explained following:
+ **Vector fields** contain a vector of numbers also known as vector embedding. Vector fields can be used to filter vectors based on specified distance metrics that measure similarity. For `HASH` indexes, the field should contain the entire vector encoded in binary format (little-endian IEEE 754). For `JSON` keys the path should reference an array of the correct size filled with numbers. Note that when a JSON array is used as a vector field, the internal representation of the array within the JSON key is converted into the format required by the selected algorithm, reducing memory consumption and precision. Subsequent read operations using the JSON commands will yield the reduced precision value.
+ **Number fields** contain a single number. Number fields can be used with the range search operator. For `HASH`, the field is expected to contain the ASCII text of a number written in the standard format of fixed- or floating-point numbers. For `JSON` fields, the numeric rules of JSON numbers must be followed. Regardless of the representation within the key, this field is converted to a 64-bit floating point number for storage within the index. Because the underlying numbers are stored in floating point with its precision limitations, the usual rules about numeric comparisons for floating point numbers apply.
+ **Tag fields** contain zero or more tag values coded as a single UTF-8 string. Tag fields can be used to filter queries for tag value equivalence with either case-sensitive or case-insensitive comparison. The string is parsed into tag values using a separator character (default is a comma but can be overridden) with leading and trailing white space removed. Any number of tag values can be contained in a single tag field.

## Vector index algorithms
<a name="vector-index-algorithms"></a>

Two vector index algorithms are supported in Valkey:
+ **Flat** – The Flat algorithm is a brute force linear processing of each vector in the index, yielding exact answers within the bounds of the precision of the distance computations. Because of the linear processing of the index, run times for this algorithm can be very high for large indexes. Flat indexes support higher ingestion speeds.
+ **Hierarchical Navigable Small Worlds (HNSW)** – The HNSW algorithm is an alternative that provides an approximate closest vector matches in exchange for substantially lower execution times. The algorithm is controlled by three parameters `M`, `EF_CONSTRUCTION` and `EF_RUNTIME`. The first two parameters are specified at index creation time and cannot be changed. The `EF_RUNTIME` parameter has a default value that is specified at index creation but can be overridden on any individual query operation afterward. These three parameters interact to balance memory and CPU consumption during ingestion and query operations as well as control the quality of the approximation of an exact KNN search (known as recall ratio).

In HNSW, the parameter M controls the maximum number of neighbors each node can connect to, shaping the index density. A higher M, such as 32 and above, produces a more connected graph, improving recall and query speed because more paths exist to reach relevant neighbors. However, it increases index size, memory use, and slows down indexing. A lower M, such as 8 and below, yields a smaller, faster-to-build index with lower memory use, but recall decreases and queries may take longer due to fewer connections.

The parameter EF\$1construction dictates how many candidate connections are evaluated when building the index. A higher EF\$1construction, such as 400 and above, means the indexer considers more paths before selecting neighbors, leading to a graph that improves both recall and query efficiency later, but at the cost of slower indexing and higher CPU and memory use during construction. A low EF\$1construction, such as 64-120, speeds up indexing and reduces resource use, but the resulting graph may reduce recall and slow queries even if EF\$1runtime is set high.

Finally, EF\$1runtime governs the breadth of the search during querying, controlling how many candidate neighbors are explored at runtime. Setting it high increases recall and accuracy, but at the cost of query latency and CPU use. A low EF\$1runtime makes queries faster and lighter, but with reduced recall. Unlike M or EF\$1construction, this parameter does not affect index size or build time, making it the parameter to tune recall versus latency trade-offs after an index is built.

Both vector search algorithms (Flat and HNSW) support an optional `INITIAL_CAP` parameter. When specified, this parameter pre-allocates memory for the indexes, resulting in reduced memory management overhead and increased vector ingestion rates. Flat indexes support better ingestion speeds than HNSW.

Vector search algorithms like HNSW may not efficiently handle deleting or overwriting of previously inserted vectors. Use of these operations can result in excess index memory consumption and/or degraded recall quality. Reindexing is one method for restoring optimal memory usage and/or recall.

## Vector search security
<a name="vector-search-security"></a>

[Valkey ACL (Access Control Lists)](https://valkey.io/topics/acl/) security mechanisms for both command and data access are extended to control the search facility. ACL control of individual search commands is fully supported. A new ACL category, `@search`, is provided and many of the existing categories (`@fast`, `@read`, `@write`, etc.) are updated to include the new commands. Search commands do not modify key data, meaning that the existing ACL machinery for write access is preserved. The access rules for `HASH` and `JSON` operations are not modified by the presence of an index; normal key-level access control is still applied to those commands.

Search commands with an index also have their access controlled through ACL. Access checks are performed at the whole-index level, not at the per-key level. This means that access to an index is granted to a user only if that user has permission to access all possible keys within the keyspace prefix list of that index. In other words, the actual contents of an index don't control the access. Rather, it is the theoretical contents of an index as defined by the prefix list which is used for the security check. Situations where a user has read and/or write access to a key but is unable to access an index containing that key are possible. Note that only read access to the keyspace is required to create or use an index – the presence or absence of write access is not considered

# Vector search features and limits
<a name="vector-search-features-limits"></a>

## Vector search availability
<a name="vector-search-availability"></a>

Vector search for Amazon ElastiCache is available with Valkey version 8.2 on node-based clusters in all AWS Regions at no additional cost. You can also use vector search on your existing clusters by upgrading from any version of Valkey, or Redis OSS to Valkey 8.2, in a [few clicks with no downtime](VersionManagement.HowTo.md).

Vector search is currently available on all ElastiCache instance types other than nodes with data tiering. Using vector search on t2, t3, and t4g instances requires increasing the memory reserve to at least 50% for micro and 30% for small instances. See [this page](redis-memory-management.md) to find out more.

## Parametric restrictions
<a name="parametric-restrictions"></a>

The following table shows limits for various vector search items:


**Vector search limits**  

| Item | Maximum value | 
| --- | --- | 
| Number of dimensions in a vector | 32768 | 
| Number of indexes that can be created | 10 | 
| Number of fields in an index | 50 | 
| FT.SEARCH TIMEOUT clause (milliseconds) | 60000 | 
| Maximum number of prefixes allowed per index | 16 | 
| Maximum length of a tag field | 10000 | 
| Maximum length of a numeric field | 256 | 
| HNSW M parameter | 2000000 | 
| HNSW EF\$1CONSTRUCTION parameter | 4096 | 
| HNSW EF\$1RUNTIME parameter | 4096 | 

## Operational restrictions
<a name="operational-restrictions"></a>

### Index Persistence and Backfilling
<a name="index-persistence-backfilling"></a>

The update process has three steps. In the first step, the HASH or JSON key is modified and the requesting client is blocked. The second step is performed in the background and updates each of the indexes that contain the modified key. In the third step, the client is unblocked. Thus, for query operations performed on the same connection as a mutation, that change is immediately visible in the search results. However, an insert or update of a key may not be visible in search results for other clients for a short period of time. During periods of heavy system load and/or heavy mutation of data, the visibility delay can become longer.

The vector search feature persists the definition of indexes, and the content of the indexes. Indexes for vector fields are saved but the indexes for TAGS and NUMERIC are not saved, meaning that they must be rebuilt when loaded externally (full sync or a reload). This means that during any operational request or event that causes a node to start or restart, the index definition and content for vectors are restored from the latest snapshot. No user action is required to initiate this. However for TAGS and NUMERIC indexes the rebuild is performed as a backfill operation as soon as data is restored. This is functionally equivalent to the system automatically executing an FT.CREATE command for each defined index. Note that the node becomes available for application operations as soon as the data is restored, but likely before index backfill has completed, meaning that backfill operations will again become visible to applications.

The completion of index backfill is not synchronized between a primary and a replica. This lack of synchronization can unexpectedly become visible to applications, so it is recommended that applications verify backfill completion on primaries and all replicas before initiating search operations.

### Scaling limits
<a name="scaling-limits"></a>

During scaling events, the index may undergo backfill as data is migrated. This will result in a reduced recall for search queries.

### Snapshot import/export and Live Migration
<a name="snapshot-import-export"></a>

The RDB files from the one cluster with search indexes can be imported to another ElastiCache Valkey cluster with version 8.2 or higher. The new cluster will rebuild the index content on loading the RDB file. However, the presence of search indexes in an RDB file limits the compatibility of that data with prior versions of Valkey. The format of the search indexes defined by the vector search functionality is only understood by another ElastiCache cluster with Valkey version 8.2 or higher. However, RDB files that do not contain indexes are not restricted in this fashion.

### Out of Memory during backfill
<a name="out-of-memory-backfill"></a>

Similar to Valkey OSS write operations, an index backfill is subjected to out-of-memory limitations. If engine memory is filled up while a backfill is in progress, all backfills are paused. If memory becomes available, the backfill process is resumed. It is possible to delete an index when backfill is paused due to out of memory.

### Transactions
<a name="transactions"></a>

The commands `FT.CREATE`, `FT.DROPINDEX`, `FT.ALIASADD`, `FT.ALIASDEL`, and `FT.ALIASUPDATE` cannot be executed in a transactional context, i.e., not within a `MULTI/EXEC` block or within a LUA or FUNCTION script.

# Choosing the appropriate configuration
<a name="choosing-configuration"></a>

Within the console experience, ElastiCache offers an easy way to choose the right instance type based on the memory and cpu requirements of your vector workload.

## Memory consumption
<a name="memory-consumption"></a>

Memory consumption is based on the number of vectors, the number of dimensions, the M-value, and the amount of non-vector data, such as metadata associated to the vector or other data stored within the instance. The total memory required is a combination of the space needed for the actual vector data, and the space required for the vector indices. The space required for Vector data is calculated by measuring the actual capacity required for storing vectors within `HASH` or `JSON` data structures and the overhead to the nearest memory slabs, for optimal memory allocations. Each of the vector indexes uses references to the vector data stored in these data structures as well as an additional copy of the vector in the index. It is advised to plan for this additional space consumption by the index.

The number of vectors depend on how you decide to represent your data as vectors. For instance, you can choose to represent a single document into several chunks, where each chunk represents a vector. Alternatively, you could choose to represent the whole document as a single vector. The number of dimensions of your vectors is dependent on the embedding model you choose. For instance, if you choose to use the AWS Titan embedding model then the number of dimensions would be 1536. Note that you should test the instance type to make sure it fits your requirements.

## Scaling your workload
<a name="scaling-workload"></a>

Vector search supports all three methods of scaling: horizontal, vertical and replicas. When scaling for capacity, vector search behaves just like regular Valkey, i.e., increasing the memory of individual nodes (vertical scaling) or increasing the number of nodes (horizontal scaling) will increase the overall capacity. In cluster mode, the `FT.CREATE` command can be sent to any primary node of the cluster and the system will automatically distribute the new index definition to all cluster members.

However, from a performance perspective, vector search behaves very differently from regular Valkey. The multi-threaded implementation of vector search means that additional CPUs yield up to linear increases in both query and ingestion throughput. Horizontal scaling yields linear increases in ingestion throughput but may reduce query throughput. If additional query throughput is required, scaling through replicas or additional CPUs is required.

# Vector Search Commands
<a name="vector-search-commands"></a>

Following are a list of supported commands for vector search.

**Topics**
+ [FT.CREATE](vector-search-commands-ft.create.md)
+ [FT.SEARCH](vector-search-commands-ft.search.md)
+ [FT.DROPINDEX](vector-search-commands-ft.dropindex.md)
+ [FT.INFO](vector-search-commands-ft.info.md)
+ [FT.\$1LIST](vector-search-commands-ft.list.md)

# FT.CREATE
<a name="vector-search-commands-ft.create"></a>

The `FT.CREATE` command creates an empty index and initiates the backfill process. Each index consists of a number of field definitions. Each field definition specifies a field name, a field type, and a path within each indexed key to locate a value of the declared type. Some field type definitions have additional sub-type specifiers.

For indexes on HASH keys, the path is the same as the hash member name. The optional `AS` clause can be used to rename the field if desired. Renaming of fields is especially useful when the member name contains special characters.

For indexes on JSON keys, the path is a JSON path to the data of the declared type. Because the JSON path always contains special characters, the `AS` clause is required.

**Syntax**

```
FT.CREATE <index-name>
ON HASH | JSON
[PREFIX <count> <prefix1> [<prefix2>...]]
SCHEMA 
(<field-identifier> [AS <alias>] 
| VECTOR [HNSW|FLAT] <attr_count> [<attribute_name> <attribute_value>])
| TAG [SEPARATOR <sep>] [CASESENSITIVE] 
| NUMERIC 
)+
```

**<index-name> (required):** This is the name you give to your index. If an index with the same name exists already, an error is returned.

**ON HASH \$1 JSON (optional):** Only keys that match the specified type are included in this index. If omitted, HASH is assumed.

**PREFIX <prefix-count> <prefix> (optional):** If this clause is specified, then only keys that begin with the same bytes as one or more of the specified prefixes will be included in this index. If this clause is omitted, all keys of the correct type will be included. A zero-length prefix would also match all keys of the correct type.

**Field types:**
+ TAG: A tag field is a string that contains one or more tag values. 
  + SEPARATOR <sep> (optional): One of the characters `,.<>{}[]"':;!@#$%^&*()-+=~` used to delimit individual tags. If omitted, the default value is `,`.
  + CASESENSITIVE (optional): If present, tag comparisons will be case-sensitive. The default is that tag comparisons are NOT case-sensitive.
+ NUMERIC: A numeric field contains a number.
+ VECTOR: A vector field contains a vector. Two vector indexing algorithms are currently supported: HNSW (Hierarchical Navigable Small World) and FLAT (brute force). Each algorithm has a set of additional attributes, some required and other optional.
  + FLAT: The Flat algorithm provides exact answers, but has runtime proportional to the number of indexed vectors and thus may not be appropriate for large data sets.
    + DIM <number> (required): Specifies the number of dimensions in a vector.
    + TYPE FLOAT32 (required): Data type, currently only FLOAT32 is supported.
    + DISTANCE\$1METRIC [L2 \$1 IP \$1 COSINE] (required): Specifies the distance algorithm.
    + INITIAL\$1CAP <size> (optional): Initial index size.
  + HNSW: The HNSW algorithm provides approximate answers, but operates substantially faster than FLAT.
    + DIM <number> (required): Specifies the number of dimensions in a vector. 
    + TYPE FLOAT32 (required): Data type, currently only FLOAT32 is supported.
    + DISTANCE\$1METRIC [L2 \$1 IP \$1 COSINE] (required): Specifies the distance algorithm.
    + INITIAL\$1CAP <size> (optional): Initial index size.
    + M <number> (optional): Number of maximum allowed outgoing edges for each node in the graph in each layer. On the layer zero, the maximal number of outgoing edges will be 2\$1M. Default is 16, the maximum is 512.
    + EF\$1CONSTRUCTION <number> (optional): Controls the number of vectors examined during index construction. Higher values for this parameter will improve recall ratio at the expense of longer index creation times. The default value is 200. Maximum value is 4096.
    + EF\$1RUNTIME <number> (optional): Controls the number of vectors to be examined during a query operation. The default is 10, and the max is 4096. You can set this parameter value for each query you run. Higher values increase query times, but improve query recall.

**RESPONSE:** OK or error.

# FT.SEARCH
<a name="vector-search-commands-ft.search"></a>

Performs a search of the specified index. The keys that match the query expression are returned.

```
FT.SEARCH <index-name> <query>
[NOCONTENT]
[RETURN <token_count> (<field-identifier> [AS <alias>])+]
[TIMEOUT timeout] 
[PARAMS <count> <name> <value> [<name> <value>]]
[LIMIT <offset> <count>]
```
+ <index> (required): This index name you want to query.
+ <query> (required): The query string, see below for details.
+ NOCONTENT (optional): When present, only the resulting key names are returned, no key values are included.
+ TIMEOUT <timeout> (optional): Lets you set a timeout value for the search command. This must be an integer in milliseconds.
+ PARAMS <count> <name1> <value1> <name2> <value2> ... (optional): `count` is of the number of arguments, i.e., twice the number of value name pairs. See the query string for usage details.
+ RETURN <count> <field1> <field2> ... (optional): count is the number of fields to return. Specifies the fields you want to retrieve from your documents, along with any aliases for the returned values. By default, all fields are returned unless the NOCONTENT option is set, in which case no fields are returned. If count is set to 0, it behaves the same as NOCONTENT.
+ LIMIT: <offset> <count>: Lets you choose a portion of the result. The first <offset> keys are skipped and only a maximum of <count> keys are included. The default is LIMIT 0 10, which returns at most 10 keys.
+ PARAMS: Two times the number of key value pairs. Param key/value pairs can be referenced from within the query expression. For more information, see [Vector search query expression](https://docs.aws.amazon.com/memorydb/latest/devguide/vector-search-overview.html#vector-search-query-expression).
+ DIALECT: <dialect> (optional): Specifies your dialect. The only supported dialect is 2.

**RESPONSE**

The command returns either an array if successful or an error.

On success, the first entry in the response array represents the count of matching keys, followed by one array entry for each matching key. Note that if the `LIMIT` option is specified it will only control the number of returned keys and will not affect the value of the first entry.

When `NOCONTENT` is specified, each entry in the response contains only the matching keyname. Otherwise, each entry includes the matching keyname, followed by an array of the returned fields. The result fields for a key consist of a set of name/value pairs. The first name/value pair is for the distance computed. The name of this pair is constructed from the vector field name prepended with "\$1\$1", and appended with "\$1score" and the value is the computed distance. The remaining name/value pairs are the members and values of the key as controlled by the `RETURN` clause. 

The query string conforms to this syntax:

```
<filtering>=>[ KNN <K> @<vector_field_name> $<vector_parameter_name> <query-modifiers> ]
```

Where:
+ <filtering>: Is either a \$1 or a filter expression. A \$1 indicates no filtering and thus all vectors within the index are searched. A filter expression can be provided to designate a subset of the vectors to be searched.
+ <vector\$1field\$1name>: The name of a vector field within the specified index.
+ <K>: The number of nearest neighbor vectors to return.
+ <vector\$1parameter\$1name>: A PARAM name whose corresponding value provides the query vector for the KNN algorithm. Note that this parameter must be encoded as a 32-bit IEEE 754 binary floating point in little-endian format.
+ <query-modifiers>: (Optional) A list of keyword/value pairs that modify this particular KNN search. Currently, two keywords are supported:
  + EF\$1RUNTIME: This keyword is accompanied by an integer value which overrides the default value of EF\$1RUNTIME specified when the index was created.
  + AS: This keyword is accompanied by a string value which becomes the name of the score field in the result, overriding the default score field name generation algorithm.

**Filter expression**

A filter expression is constructed as a logical combination of Tag and Numeric search operators contained within parentheses.

**Tag**

The tag search operator is specified with one or more strings separated by the \$1 character. A key will satisfy the tag search operator if the indicated field contains any one of the specified strings.

```
@<field_name>:{<tag>}
or
@<field_name>:{<tag1> | <tag2>}
or
@<field_name>:{<tag1> | <tag2> | ...}
```

For example, the following query will return documents with blue OR black OR green color.

`@color:{blue | black | green}`

As another example, the following query will return documents containing "hello world" or "hello universe".

`@description:{hello world | hello universe}`

**Numeric range**

Numeric range operator allows for filtering queries to only return values that are in between a given start and end value. Both inclusive and exclusive range queries are supported. For simple relational comparisons, \$1inf, -inf can be used with a range query. The syntax for a range search operator is:

```
@<field_name>:[ [(] <bound> [(] <bound>]
```

...where <bound> is either a number or \$1inf or -inf. Bounds without a leading open paren are inclusive, whereas bounds with the leading open paren are exclusive. 

Use the following table as a guide for mapping mathematical expressions to filtering queries:

```
min <= field <= max         @field:[min max]
min < field <= max          @field:[(min max]
min <= field < max            @field:[min (max]
min < field < max            @field:[(min (max]
field >= min                @field:[min +inf]
field > min                    @field:[(min +inf]
field <= max                @field:[-inf max]
field < max                    @field:[-inf (max]
field == val                @field:[val val]
```

**Logical operators**

Multiple tags and numeric search operators can be used to construct complex queries using logical operators.

**Logical AND**

To set a logical AND, use a space between the predicates. For example:

`query1 query2 query3`

**Logical OR**

To set a logical OR, use a space between the predicates. For example:

`query1 | query2 | query3`

**Logical negation**

Any query can be negated by prepending the `-` character before each query. Negative queries return all entries that don't match the query. This also includes keys that don't have the field.

For example, a negative query on @genre:\$1comedy\$1 will return all books that are not comedy AND all books that don't have a genre field.

The following query will return all books with "comedy" genre that are not published between 2015 and 2024, or that have no year field: @genre:[comedy] -@year:[2015 2024]

**Operator precedence**

Typical operator precedence rules apply, i.e., logical NEGATE is the highest priority, followed by logical AND then logical OR with the lowest priority. Parentheses can be used to override the default precedence rules.

*Examples of combining logical operators*

Logical operators can be combined to form complex filter expressions.

The following query will return all books with "comedy" or "horror" genre (AND) published between 2015 and 2024: `@genre:[comedy|horror] @year:[2015 2024]`

The following query will return all books with "comedy" or "horror" genre (OR) published between 2015 and 2024: `@genre:[comedy|horror] | @year:[2015 2024]`

The following query will return all books that either don't have a genre field, or have a genre field not equal to "comedy", that are published between 2015 and 2024: `-@genre:[comedy] @year:[2015 2024]`

# FT.DROPINDEX
<a name="vector-search-commands-ft.dropindex"></a>

**Syntax**

```
FT.DROPINDEX <index-name>
```

The specified index is deleted. Returns OK or an error if that index doesn't exist.
+ <index-name> (required): The name of the index to delete.

# FT.INFO
<a name="vector-search-commands-ft.info"></a>

**Syntax**

```
FT.INFO <index-name>
```

Vector search augments the [FT.INFO](https://valkey.io/commands/info/) command with several additional sections of statistics and counters. A request to retrieve the section SEARCH will retrieve all of the following statistics:


| Key name | Value type | Description | 
| --- | --- | --- | 
| index\$1name | string | Name of the index | 
| index\$1options | string | Reserved. Currently set to "0" | 
| index\$1definition | array | See below for definition of these array elements. | 
| attributes | array of attribute information | One element in this array for each defined attribute, see below for attribute information definition. | 
| num\$1docs | integer | Number of keys currently contained in the index | 
| num\$1terms | integer | Reserved. Currently set to "0". | 
| record\$1count | integer | The sum of the "size" field for each attribute. | 
| hash\$1indexing\$1failures | integer | Number of times that an attribute couldn't be converted to the declared attribute type. Despite the name this also applies to JSON keys. | 
| backfill\$1in\$1progress | integer | If a backfill is currently in progress this will be a '1' otherwise it will be a '0' | 
| backfill\$1percent\$1complete | float | Estimate of backfill completion, a fractional number in the range [0..1] | 
| mutation\$1queue\$1size | integer | Number of keys waiting to update the index. | 
| recent\$1mutations\$1queue\$1delay | integer | Estimate of delay (in seconds) of index update. 0 if no updates are in progress. | 
| state | string | Backfill state: "ready" indicates that backfill completed successfully. "backfill\$1in\$1progress" indicates that backfill is proceeding. "backfill\$1paused\$1by\$1oom" means that backfilling has been paused due to a low memory condition. Once the low memory condition is resolved, backill will continue. | 

The index\$1definition structure is an array of key/value pairs defined as:


| Key name | Value type | Description | 
| --- | --- | --- | 
| key\$1type | string | Either the string 'JSON' or the string 'HASH' | 
| prefixes | array | Each element in the array is a defined prefix for the index. If no prefixes were specified when the index was create, this array will have 0 entries. | 
| default\$1score | string | Reserved. Currently set to "1" | 

Attribute information: Attribute information is type-specific.

Numeric attributes:


| Key | Value type | Description | 
| --- | --- | --- | 
| identifier | string | Location of the attribute within a key. Hash member name or JSON path | 
| alias | string | Name of attribute used in query descriptions. | 
| type | string | The string "NUMERIC" | 
| size | integer | The number of keys with valid numeric values in this attribute. | 

Tag attributes:


| Key name | Value type | Description | 
| --- | --- | --- | 
| identifier | string | Location of the attribute within a key. Hash member name or JSON path | 
| alias | string | Name of attribute used in query descriptions. | 
| type | string | The string "TAG" | 
| SEPARATOR | character | The separator character defined when the index was created | 
| CASESENSITIVE | n/a | This key has no associated value. It is present only if the attribute was created with this option. | 
| size | integer | The number of keys with valid tag values in this attribute | 

Vector attributes:


| Key name | Value type | Description | 
| --- | --- | --- | 
| identifier | string | Location of the attribute within a key. Hash member name or JSON path | 
| alias | string | Name of attribute used in query descriptions. | 
| type | string | The string "VECTOR" | 
| index | character | For further description of vector index, see below. | 

Vector index description:


| Key name | Value type | Description | 
| --- | --- | --- | 
| capacity | string | Current capacity of index | 
| dimensions | string | Number of elements in each vector | 
| distance\$1metric | string | One of "COSINE", "L2" or "IP" | 
| size | array  | Description of vector index, see below. | 
| data\$1type | string | Declared datatype. Only "FLOAT32" is currently supported. | 
| algorithm | array  | Further description of the vector search algorithm. | 

FLAT Vector search algorithm Description:


| Key name | Value type | Description | 
| --- | --- | --- | 
| name | string | Algorithm name: FLAT | 
| block\$1size | number | Size of a block of the FLAT index. | 

HNSW Vector Index Description:


| Key name | Value type | Description | 
| --- | --- | --- | 
| name | string | Algorithm name: HNSW | 
| m | number | The "M" parameter for HNSW | 
| ef\$1construction | number | The "ef\$1construction" parameter for HNSW | 
| ef\$1runtime | number | The "ef\$1runtime" parameter for HNSW. | 

# FT.\$1LIST
<a name="vector-search-commands-ft.list"></a>

List all indexes.

**Syntax**

```
FT._LIST 
```

Returns an array of strings that are the names of currently defined index.