Redis Search, a module for Redis, lets you do full-text and vector similarity search on your data. It’s not just a key-value store anymore; it’s a powerful indexing engine.
Let’s see it in action. Imagine you have a collection of product descriptions and you want to find products based on natural language queries, or even by similarity to an existing product’s description (using vector embeddings).
First, you need to install the Redis Search module. If you’re using Docker, it’s as simple as:
docker run -d -p 6379:6379 --name redis-stack redis/redis-stack:latest
This command pulls the redis/redis-stack image, which includes Redis and the Redis Search module, and runs it in detached mode, exposing Redis on port 6379.
Now, let’s add some data and create an index. We’ll use the redis-cli for this.
127.0.0.1:6379> FT.CREATE my_index ON HASH PREFIX 1 product: SCHEMA title TEXT weight 5 description TEXT weight 1 price NUMERIC category TAG
Here’s what’s happening:
FT.CREATE my_index: We’re creating a new search index namedmy_index.ON HASH: We’re telling Redis Search to index data stored as Redis Hashes.PREFIX 1 product:: This tells Redis Search to only consider keys that start withproduct:when building this index. This is crucial for organizing your indexed data.SCHEMA title TEXT weight 5 description TEXT weight 1 price NUMERIC category TAG: This defines the fields within our Hashes that we want to index.title TEXT weight 5: Thetitlefield will be indexed for full-text search, and it has a higher weight (5) thandescription, meaning matches in the title are more relevant.description TEXT weight 1: Thedescriptionfield is also indexed for full-text search, with a lower weight (1).price NUMERIC: Thepricefield is indexed as a number, allowing for range queries (e.g., find products between $10 and $50).category TAG: Thecategoryfield is indexed as a tag, which is great for exact matching and filtering (e.g., find products in the 'electronics' category).
Now, let’s add some products to Redis:
127.0.0.1:6379> HMSET product:1 title "Smart LED Bulb" description "A smart LED bulb that can change colors and be controlled via app." price 19.99 category "smart home, lighting"
127.0.0.1:6379> HMSET product:2 title "Wireless Bluetooth Speaker" description "Portable speaker with great bass and long battery life." price 49.50 category "electronics, audio"
127.0.0.1:6379> HMSET product:3 title "Ergonomic Office Chair" description "Comfortable chair for long working hours, adjustable height and lumbar support." price 199.00 category "furniture, office"
127.0.0.1:6379> HMSET product:4 title "Gaming Mouse RGB" description "High-precision gaming mouse with customizable RGB lighting and programmable buttons." price 55.75 category "electronics, gaming"
With data indexed, we can perform searches.
Full-Text Search:
To find products related to "smart lighting":
127.0.0.1:6379> FT.SEARCH my_index "smart lighting"
This will return results where both "smart" and "lighting" appear in the indexed fields, prioritizing matches in the title due to its higher weight.
To search specifically within a category:
127.0.0.1:6379> FT.SEARCH my_index "@category:{smart home}"
This query will only return products belonging to the "smart home" category.
Vector Search:
For vector search, you first need to generate vector embeddings for your data. This is typically done using external ML models. Let’s assume you have these embeddings. You’d add them to your Redis Hashes, perhaps in a field named description_vector.
127.0.0.1:6379> HMSET product:1 title "Smart LED Bulb" ... description_vector "[0.1, 0.2, ..., 0.9]"
You then need to add a vector field to your schema and re-index (or create a new index).
127.0.0.1:6379> FT.ALTER my_index ADD_FIELD description_vector VECTOR HNSW 64.0 MIN 10 MAX 10000 INITIAL_CAP 1000000 TYPE FLOAT64
This command adds a description_vector field using the HNSW (Hierarchical Navigable Small Worlds) algorithm, which is highly efficient for approximate nearest neighbor search. 64.0 is the M parameter for HNSW, controlling graph complexity. MIN 10 MAX 10000 define the range for efConstruction, controlling build time vs. search accuracy. INITIAL_CAP is the initial capacity of the index.
Now you can search for vectors similar to a query vector:
127.0.0.1:6379> FT.SEARCH my_index "*=>[ KNN 3 @description_vector $query_vec]" PARAMS query_vec "[0.15, 0.25, ..., 0.85]" RETURN 2 title description_vector
This query finds the 3 nearest neighbors (KNN 3) to the provided query_vec based on the description_vector field. PARAMS is used to pass the vector query efficiently. RETURN specifies which fields to get back.
The true power of Redis Search lies in its ability to combine these search types. You can perform a full-text search and then, within those results, find the most similar vectors, or vice-versa.
A common pitfall is not explicitly defining the PREFIX when creating an index. If you have multiple types of data in Redis that happen to share common key patterns, an index without a PREFIX could unintentionally try to index everything, leading to performance degradation or unexpected results. Always scope your indexes precisely.
The next step is exploring advanced query syntax, fuzzy matching, and geospatial indexing.