Using Redis Stack for Full‑Text Search with RediSearch and JSON
This tutorial explains how to leverage Redis Stack modules—especially RediSearch and RedisJSON—to store movie data, build a searchable JSON index, and perform advanced full‑text queries, highlighting, sorting, pagination, custom tokenization, scoring, and index aliasing, with Go code examples.
Preface
Redis is widely known as a cache, but its additional modules such as RedisJSON , RediSearch , RedisTimeSeries , and RedisBloom extend its capabilities to handle JSON data, full‑text search (including fuzzy, vector, and geo queries), time‑series data, and probabilistic calculations. All these modules can be imported on demand or used together via Redis Stack .
This article demonstrates how to use Redis for full‑text search.
Redis Full‑Text Search
Full‑Text Search Basics
Full‑text search is a technique that quickly finds relevant documents based on user‑provided words or sentences.
The core concepts include:
Tokenization: splitting a document into individual terms.
Inverted Index: a structure that maps terms to the documents containing them.
Relevance Scoring: assigning a score to each result based on its relevance.
Example Dataset
We will use a public movie dataset and keep only a few fields for simplicity:
_id: unique identifier
title: movie title
directors: director names
genres: movie genres
summary: brief description
rating: numeric rating
Data is stored in Redis as JSON using the JSON.SET command:
JSON.SET movieID:1 $ '{"directors":"马丁·里特","genres":["剧情","动作","西部"],"rating":8.0,"title":"野狼 Hombre","summary":"约翰·罗塞尔自幼是老罗塞尔先生从战俘中带回来并抚养他长大的,但是他生性豪放不羁……"}'Note that Redis keys are always strings; in this tutorial we use the pattern movieID:12345 .
Batch import with Go:
func BuildDataset() {
movies, _ := ReadMovieJSON()
rds := getRedisClient()
ctx := context.Background()
for _, v := range movies {
b, _ := json.Marshal(v)
if r := rds.JSONSet(ctx, "movieID:"+v.ID, "$", b); r.Err() != nil {
panic(r.Err())
}
}
}Creating the Index
To enable full‑text search we create an index with FT.CREATE :
FT.CREATE movies ON JSON
PREFIX 1 movieID:
LANGUAGE Chinese
SCHEMA
$.title as title TEXT WEIGHT 3
$.directors.*.name as directors TAG
$.genres.* as genres TAG
$.summary as summary TEXT
$.rating.average as rating NUMERICThe command means:
We create a JSON‑backed index named movies .
The index applies to all keys with the prefix movieID: .
Chinese tokenization is used.
Indexed fields: title (TEXT, weight 3) directors (TAG) genres (TAG) summary (TEXT) rating (NUMERIC)
Indexes are independent objects; dropping an index does not delete the underlying key‑value data. New or updated documents are indexed automatically, while existing documents are indexed asynchronously after the index is created.
Using Full‑Text Search
Basic Queries
Search any field for the word "爱情": FT.SEARCH movies '爱情'
Return only specific fields: FT.SEARCH movies '爱情' RETURN 2 title directors
Highlight matches in the title field: FT.SEARCH movies '爱情' RETURN 2 title directors HIGHLIGHT FIELDS 1 title TAGS <span> </span>
Sort results by rating descending: FT.SEARCH movies '爱情' RETURN 3 title directors rating SORTBY rating DESC
Paginate results (first 10): FT.SEARCH movies '爱情' RETURN 3 title directors rating SORTBY rating DESC LIMIT 0 10
Field‑specific text search (title contains "爱情"): FT.SEARCH movies '@title:爱情' RETURN 2 title directors
Tag field match (director is "马丁·里特"): FT.SEARCH movies '@directors:{马丁·里特}' RETURN 2 title directors
Compound Conditions
OR – genre is drama or action: FT.SEARCH movies '@genres:{剧情|动作}' RETURN 2 title directors
AND – genre is drama or action AND rating ≥ 8.0: FT.SEARCH movies '(@genres:{剧情|动作})(@rating:[8.0,+inf])' RETURN 3 title directors rating
Prefix, Suffix & Fuzzy Search
FT.SEARCH movies '@title:爱*' RETURN 1 title
FT.SEARCH movies '@title:*情' RETURN 1 title
FT.SEARCH movies '@title:*命*' RETURN 1 title
FT.SEARCH movies '@title:%人生%' RETURN 1 title
Custom Tokenization
Redis offers limited custom tokenization compared with Elasticsearch:
Stopwords can be set via the STOPWORDS option of FT.CREATE .
Synonyms are added with FT.SYNUPDATE . Example: FT.SYNUPDATE movies group1 爱情 凌虚 After that, FT.SEARCH movies '爱情' is equivalent to FT.SEARCH movies '凌虚' .
Custom Scoring
Redis supports several scoring algorithms:
TFIDF (default)
TFIDF.DOCNORM
BM25 (used by Elasticsearch)
DISMAX
DOCSCORE
HAMMING
FT.SEARCH movies '爱情' RETURN 0 WITHSCORES SCORER BM25For other custom scoring methods you need to write a Redis module in C or a language with a C interface.
Index Alias
Creating an alias allows you to switch the underlying index without changing client code:
Create alias: FT.ALIASADD aliasName movies
Search via alias: FT.SEARCH aliasName '爱情' RETURN 0
Update alias to a new index: FT.ALIASUPDATE aliasName anotherIndex
Delete alias: FT.ALIASDEL aliasName
Go Helper Functions
Utility functions for executing arbitrary Redis commands using the go-redis client:
func cmdStringToArgs(rdscmd string) (result []interface{}) {
re := regexp.MustCompile(`\s+`)
slice := re.Split(rdscmd, -1)
for _, v := range slice {
if v != "" && v != " " {
result = append(result, v)
}
}
return
}
func ExcuteCommand(rdscmd string) {
rds := getRedisClient()
ctx := context.Background()
args := cmdStringToArgs(rdscmd)
res, err := rds.Do(ctx, args...).Result()
if err != nil {
panic(err)
}
fmt.Println("RESULT:", res)
}Test case illustrating several search commands:
func TestExcuteCommand(t *testing.T) {
cases := []string{
`FT.SEARCH movies '爱情'`,
`FT.SEARCH movies '爱情' RETURN 2 title directors`,
// ... more cases
}
for _, v := range cases {
ExcuteCommand(v)
}
}Conclusion
Compared with Elasticsearch , the flagship full‑text engine, Redis offers fewer features (e.g., limited custom tokenization and scoring) but still provides all essential full‑text capabilities. For small‑to‑medium data volumes and simple search scenarios, Redis can be more resource‑efficient and faster than running an Elasticsearch cluster.
References:
https://redis.io/docs/latest/develop/interact/search-and-query/
https://redis.io/docs/latest/commands/ft.create/
https://redis.io/docs/latest/commands/ft.search/
System Architect Go
Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.