RediSearch is a powerful text search and secondary indexing engine, built on top of Redis as a Redis module.
Unlike Redis search libraries, it does not use Redis’ internal data structures. Using its own highly optimized data structures and algorithms, RediSearch allows for advanced search features, with high performance and a small memory footprint. It can perform simple text searches as well as complex structured queries, filtering by numeric properties and geographical distances
To learn about how to use RediSearch read:
1 Build readiserch
The following compile template was run on CentOS 8.
1.1 Pre-requisites
Install this libraries as user root:
dnf install gcc-c++
1.2 Download
From redis directory download RediSearch code from git.
su - redis cd /home/redis git clone https://github.com/RediSearch/RediSearch.git cd RediSearch ls -l
drwxrwxr-x 2 redis redis 140 Apr 24 00:31 cmake
-rw-rw-r-- 1 redis redis 6575 Apr 24 00:31 CMakeLists.txt
-rw-rw-r-- 1 redis redis 331 Apr 24 00:31 codecov.yml
drwxrwxr-x 4 redis redis 39 Apr 24 00:31 deps
drwxrwxr-x 3 redis redis 37 Apr 24 00:31 docker
drwxrwxr-x 4 redis redis 4096 Apr 24 00:31 docs
-rwxrwxr-x 1 redis redis 727 Apr 24 00:31 getver
-rw-rw-r-- 1 redis redis 5793 Apr 24 00:31 LICENSE
-rw-rw-r-- 1 redis redis 7784 Apr 24 00:31 Makefile
-rw-rw-r-- 1 redis redis 2165 Apr 24 00:31 mkdocs.yml
-rwxrwxr-x 1 redis redis 6908 Apr 24 00:31 pack.sh
-rw-rw-r-- 1 redis redis 557 Apr 24 00:31 ramp.yml
-rw-rw-r-- 1 redis redis 12555 Apr 24 00:31 README.md
drwxrwxr-x 10 redis redis 4096 Apr 24 00:31 src
drwxrwxr-x 2 redis redis 131 Apr 24 00:31 srcutil
-rwxrwxr-x 1 redis redis 2170 Apr 24 00:31 system-setup.py
drwxrwxr-x 8 redis redis 93 Apr 24 00:31 tests
1.3 Compile
From RediSearch create a build directory and from it, run cmake
.
mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
When running the command cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
if the gcc-c++ is not installed
you will get the following error:
CMake Error at CMakeLists.txt:6 (project): No CMAKE_CXX_COMPILER could be found. Tell CMake where to find the compiler by setting either the environment variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path to the compiler, or to the compiler name if it is in the PATH. Error: --system-information failed on internal CMake!
To solve the problem you can run the follwoing command:
yum install gcc-c++
Go back to RediSearch directory and from it, run make
.
Run this commands with root privileges or user root:
cd .. make
Scanning dependencies of target rscore
[ 0%] Building C object CMakeFiles/rscore.dir/src/alias.c.o
[ 1%] Building C object CMakeFiles/rscore.dir/src/buffer.c.o
[ 1%] Building C object CMakeFiles/rscore.dir/src/byte_offsets.c.o
[ 2%] Building C object CMakeFiles/rscore.dir/src/cndict_loader.c.o
...
[ 99%] Building C object src/rmutil/CMakeFiles/test_vector.dir/test_vector.c.o
[100%] Linking C executable test_vector
[100%] Built target test_vector
When building RediSearch, the following error may appear:
Makefile:3: deps/readies/mk/main: No such file or directory Makefile:105: /defs: No such file or directory Makefile:109: /rules: No such file or directory ./pack.sh: line 54: /home/redis/RediSearch/deps/readies/shibumi/functions: No such file or directory ./pack.sh: line 54: /home/redis/RediSearch/deps/readies/shibumi/functions: No such file or directory make: *** No rule to make target `/rules'. Stop.
This is because there are files that haven't been cloned correctly with the git clone command.
In order to fix this, run the following commands:
cd /home/redis/RediSearch/deps/ rm -rf readies/ git clone https://github.com/RedisLabsModules/readies.git
Now the readies folder should have the following files:
ls readies/
bin cetara docs LICENSE mk paella README.md shibumi wd40
redisearch.so
file in build directory.
1.4 Start Redis with ReadiSeach
Copy redisearch.so
to /home/redis/bin/
mkdir -p /home/redis/bin/ mv build/redisearch.so /home/redis/bin/
redis-server --loadmodule /home/redis/bin/redisearch.so 50239:C 01 Dec 2019 20:52:27.598 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 50239:C 01 Dec 2019 20:52:27.598 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=50239, just started 50239:C 01 Dec 2019 20:52:27.598 # Configuration loaded 50239:M 01 Dec 2019 20:52:27.599 * Increased maximum number of open files to 10032 (it was originally set to 256). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.7 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 50239 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 50239:M 01 Dec 2019 20:52:27.600 # Server initialized 50239:M 01 Dec 2019 20:52:27.951 * <ft> RediSearch version 99.99.99 (Git=v1.6.0-373-gac16a4d8) 50239:M 01 Dec 2019 20:52:27.951 * <ft> Low level api version 1 initialized successfully 50239:M 01 Dec 2019 20:52:27.951 * <ft> concurrent writes: OFF, gc: ON, prefix min length: 2, prefix max expansions: 200, query timeout (ms): 500, timeout policy: return, cursor read size: 1000, cursor max idle (ms): 300000, max doctable size: 1000000, search pool size: 20, index pool size: 8, 50239:M 01 Dec 2019 20:52:27.951 * <ft> Initialized thread pool! 50239:M 01 Dec 2019 20:52:27.951 * Module 'ft' loaded from redis/redisearch.so 50239:M 01 Dec 2019 20:52:27.951 * Ready to accept connections
2 Continue installation
3 Indexes
RediSearch is a Redis module that provides querying, secondary indexing, and full-text search for Redis. To use RediSearch, you first declare indexes on your Redis data. You can then use the RediSearch query language to query that data. RediSearch uses compressed, inverted indexes for fast indexing with a low memory footprint. RediSearch indexes enhance Redis by providing exact-phrase matching, fuzzy search, and numeric filtering, among many other features.
3.1 Creating an index
Creates an index with the given spec. The index name will be used in all the key names so keep it short!
FT.CREATE {index} [MAXTEXTFIELDS] [TEMPORARY {seconds}] [NOOFFSETS] [NOHL] [NOFIELDS] [NOFREQS] [STOPWORDS {num} {stopword} ...] SCHEMA {field} [TEXT [NOSTEM] [WEIGHT {weight}] [PHONETIC {matcher}] | NUMERIC | GEO | TAG [SEPARATOR {sep}] ] [SORTABLE][NOINDEX] ...
Creating an index with fields and weights (default weight is 1.0)
FT.CREATE products SCHEMA title TEXT price NUMERIC
3.2 Add documents
To add documents to and index
FT.ADD {index} {docId} {score} [NOSAVE] [REPLACE [PARTIAL]] [LANGUAGE {language}] [PAYLOAD {payload}] [IF {condition}] FIELDS {field} {value} [{field} {value}...]
FT.ADD products prod1 1.0 FIELDS title "Apple AirPods Pro" price 250 FT.ADD products prod2 1.0 FIELDS title "Acer Aspire 5" price 445 FT.ADD products prod3 1.0 FIELDS title "Bose SoundLink Color II" price 129 FT.ADD products prod4 1.0 FIELDS title "DJI Mini 2 – Ultralight and Foldable" price 449 FT.ADD products prod5 1.0 FIELDS title "Toshiba 32 LCD TV" price 250 FT.ADD products prod6 1.0 FIELDS title "Fujifilm Instax Mini 11" price 99 FT.ADD products prod7 1.0 FIELDS title "Rolex Cosmograph Daytona Ice Blue" price 75700 FT.ADD products prod8 1.0 FIELDS title "GoPro HERO8 Black 4K Waterproof Action Camera" price 259.99 FT.ADD products prod9 1.0 FIELDS title "Samsung 42 LCD TV" price 350 FT.ADD products prod10 1.0 FIELDS title "Panasonic LUMIX FZ80 4K Digital Camera" price 297.99 FT.ADD products prod11 1.0 FIELDS title "LG Electronics 32-Inch 720p LED TV" price 520
3.3 Search
To perform a search on an index
FT.SEARCH {index} {query} [NOCONTENT] [VERBATIM] [NOSTOPWORDS] [WITHSCORES] [WITHPAYLOADS] [WITHSORTKEYS] [FILTER {numeric_field} {min} {max}] ... [GEOFILTER {geo_field} {lon} {lat} {raius} m|km|mi|ft] [INKEYS {num} {key} ... ] [INFIELDS {num} {field} ... ] [RETURN {num} {field} ... ] [SUMMARIZE [FIELDS {num} {field} ... ] [FRAGS {num}] [LEN {fragsize}] [SEPARATOR {separator}]] [HIGHLIGHT [FIELDS {num} {field} ... ] [TAGS {open} {close}]] [SLOP {slop}] [INORDER] [LANGUAGE {language}] [EXPANDER {expander}] [SCORER {scorer}] [PAYLOAD {payload}] [SORTBY {field} [ASC|DESC]] [LIMIT offset num]
Search example 1
FT.SEARCH products "lcd tv"
1) (integer) 2
2) "prod2"
3) 1) "title"
2) "Samsung 42 LCD TV"
3) "price"
4) "350"
4) "prod1"
5) 1) "title"
2) "Toshiba 32 LCD TV"
3) "price"
4) "250"
Search example 2
FT.SEARCH products "lcd tv" FILTER price 300 400
1) (integer) 1
2) "prod2"
3) 1) "title"
2) "Samsung 42 LCD TV"
3) "price"
4) "350"
3.4 Sorting by indexed fields
As of RediSearch 0.15, it is possible to bypass the scoring function mechanism, and order search results by the value of different document properties (fields) directly - even if the sorting field is not used by the query. For example, you can search for first name and sort by last name.
TO DO
This section is incomplete and will be concluded as soon as possible.3.5 Dropping the index
FT.DROP products
3.6 Minimum query characters (MINPREFIX)
We can change the minimum number of characters we allow for prefix queries (e.g. bla* ). Setting it to 1 can hurt performance (default value is 2). It must be done before the creation of the index.
FT.CONFIG SET MINPREFIX 3
3.7 Maximum number of expansions (MAXEXPANSIONS)
We can change the maximum number of expansions we allow for query prefixes. Setting it too high can cause performance issues (default value is 200). If MAXEXPANSIONS is reached, the query will continue with the first acquired results and will not search anymore.
FT.CONFIG SET MAXEXPANSIONS 1000
Let's explain how this works and how it affects to the search:
Imagine we set the MAXEXPANSIONS to 2, MINPREFIX to 1 and our index looks like the following:
index name ----------------------------- 0001 Red parrot 0002 Orange parrot 0003 White paper 0004 Blue pen 0005 Green pickle
If we do the following query:
FT.SEARCH myIndex "@name: Green p*"
The output returns no result. That's because the redisearch indexes all the words he find starting by p, up to MAXEXPANSIONS.
In our case, MAXEXPANSIONS = 2, so the words starting by p in alphabetical order:
parrot --> position 2 Still in MAXEXPANSIONS range --> (Red parrot considered in query) --> (Orange parrot considered in query) paper --> position 1 Still in MAXEXPANSIONS range --> (White paper considered in query) ------------------------------------------------------------------------------------------------------ Here MAXEXPANSIONS is full pen --> position 3 Not in MAXEXPANSIONS range --> (Blue pen NOT considered in query) pickle --> position 4 Not in MAXEXPANSIONS range --> (Green pickle NOT considered in query)
And because neither White paper, Red parrot nor Orange parrot satisfy the Green p* query, therefore no result is returned.
4 Auto-complete suggestions
The auto-suggest is independent from the search index and needs to be built independently, as you can see.
FT.SUGADD {key} {string} {score} [INCR] [PAYLOAD {payload}]
You have three options:
- Suggestions can have payloads, which can be any string you want, or even whole documents as JSON (they are not searchable though). So just put whatever payload you want for a suggestion.
- The index itself supports prefix searches disconnected from the auto-complete. You can use a prefix query (FT.SEARCH idx "foo*") to search documents containing a prefix.
- Best method: take the top completion suggesion and run that as a search query.
FT.SUGADD autocomplete "hello world" 100 FT.SUGGET autocomplete "he"
1) "hello world"
4.1 Suggestions length
You can query the length of a suggestion index (key).
FT.SUGLEN autocomplete
(integer) 1
4.2 Drop suggestions
To drop a suggestions you should use the DEL
command. The command will return
the length of the suggesions deleted. If suggestion index does not exits, it will return 0.
DEL autocomplete
(integer) 1
5 Aggregations
Aggregations are a way to process the results of a search query, group, sort, transform them and extract analytic insights from them.
5.1 Core concepts
The basic idea of an aggregate query is this:
- Perform a search query, filtering for records you wish to process.
-
Build a pipeline of operations that transform the results by zero or more steps of:
- Group and Reduce: grouping by fields in the results, and applying reducer functions on each group.
- Sort: sort the results based on one or more fields.
- Apply Transformations: Apply mathematical and string functions on fields in the pipeline, optionally creating new fields or replacing existing ones.
- Limit: Limit the result, regardless of sorting the result.
- Filter: Filter the results (post-query) based on predicates relating to its values.
The pipeline is dynamic and reentrant, and every operation can be repeated. For example, you can group by property X, sort the top 100 results by group size, then group by property Y and sort the results by some other property, then apply a transformation on the output.
5.2 Aggregate request format
The aggregate request's syntax is defined as follows:
FT.AGGREGATE {index_name:string} {query_string:string} [VERBATIM] [LOAD {nargs:integer} {property:string} ...] [GROUPBY {nargs:integer} {property:string} ... REDUCE {FUNC:string} {nargs:integer} {arg:string} ... [AS {name:string}] ... ] ... [SORTBY {nargs:integer} {string} ... [MAX {num:integer}] ... ] ... [APPLY {EXPR:string} AS {name:string} ] ... [FILTER {EXPR:string}] ... [LIMIT {offset:integer} {num:integer} ] ...
5.3 Examples
Let's create first the index we will be working on and let's fill it with some documents. Afterwards we shall see some examples.
Create an index
FT.CREATE ptest SCHEMA name TEXT SORTABLE price NUMERIC SORTABLE size TAG color TAG brand TEXT
Add documents to the index
FT.ADD ptest I00001 1.0 FIELDS name "Boli BIC black" price 0.8 color "BLACK" brand "BIC" FT.ADD ptest I00002 1.0 FIELDS name "Boli BIC blue" price 0.8 color "BLUE" brand "BIC" FT.ADD ptest I00003 1.0 FIELDS name "Boli BIC red" price 0.8 color "RED" brand "BIC" FT.ADD ptest I00004 1.0 FIELDS name "Boli BIC multicolor" price 3.8 color "BLACK,RED,BLUE" brand "BIC" FT.ADD ptest I00005 1.0 FIELDS name "Boli Standler punta fina" price 2.8 color "BLUE" brand "STANDLER" FT.ADD ptest I00006 1.0 FIELDS name "Boli Standler punta fina" price 2.8 color "RED" brand "STANDLER" FT.ADD ptest I00007 1.0 FIELDS name "Boli Standler punta fina" price 2.8 color "GREEN" brand "STANDLER" FT.ADD ptest I00008 1.0 FIELDS name "Pilot Gold" price 5.8 color "GOLD" brand "PILOT" FT.ADD ptest I00009 1.0 FIELDS name "Pilot Silver" price 4.8 color "SILVER" brand "PILOT"
Return the maximum price of all documents
FT.AGGREGATE ptest * GROUPBY 0 REDUCE MAX 1 @price AS max_price
1) (integer) 1
2) 1) "max_price"
2) "5.8"
Return the minimum price of all documents
FT.AGGREGATE ptest * GROUPBY 0 REDUCE MIN 1 @price AS min_price
1) (integer) 1
2) 1) "min_price"
2) "0.8"
Return the total count of all documents
FT.AGGREGATE ptest * GROUPBY 0 REDUCE COUNT 0 AS total_count
1) (integer) 1
2) 1) "total_count"
2) "9"
Return all distinct brands
FT.AGGREGATE ptest * GROUPBY 1 @brand
1) (integer) 3
2) 1) "brand"
2) "STANDLER"
3) 1) "brand"
2) "BIC"
4) 1) "brand"
2) "PILOT"
Return all distinct colors (considering every color within color property as a single color)
FT.AGGREGATE ptest * GROUPBY 1 @color APPlY split(@color) AS dist_color GROUPBY 1 @dist_color
1) (integer) 6
2) 1) "dist_color"
2) "BLUE"
3) 1) "dist_color"
2) "RED"
4) 1) "dist_color"
2) "SILVER"
5) 1) "dist_color"
2) "GREEN"
6) 1) "dist_color"
2) "BLACK"
7) 1) "dist_color"
2) "GOLD"
Return the result of the query sorted by name
FT.AGGREGATE ptest * SORTBY 1 @name
1) (integer) 9
2) 1) "name"
2) "boli bic black"
3) 1) "name"
2) "boli bic blue"
4) 1) "name"
2) "boli bic multicolor"
5) 1) "name"
2) "boli bic red"
6) 1) "name"
2) "boli standler punta fina"
7) 1) "name"
2) "boli standler punta fina"
8) 1) "name"
2) "boli standler punta fina"
9) 1) "name"
2) "pilot gold"
10) 1) "name"
2) "pilot silver"
5.4 Supported GROUPBY reducers
Reducer | Format | Description |
---|---|---|
COUNT | REDUCE COUNT 0 | Count the number of records in each group. |
COUNT_DISTINCT | REDUCE COUNT_DISTINCT 1 {property} | Count the number of distinct values for property. |
COUNT_DISTINCTISH | REDUCE COUNT_DISTINCTISH 1 {property} | Same as COUNT_DISTINCT - but provide an approximation instead of an exact count, at the expense of less memory and CPU in big groups. |
SUM | REDUCE SUM 1 {property} | Return the sum of all numeric values of a given property in a group. Non numeric values if the group are counted as 0. |
MIN | REDUCE MIN 1 {property} | Return the minimal value of a property, whether it is a string, number or NULL. |
MAX | REDUCE MAX 1 {property} | Return the maximal value of a property, whether it is a string, number or NULL. |
AVG | REDUCE AVG 1 {property} | Return the average value of a numeric property. This is equivalent to reducing by sum and count, and later on applying the ratio of them as an APPLY step. |
STDDEV | REDUCE STDDEV 1 {property} | Return the standard deviation of a numeric property in the group. |
QUANTILE | REDUCE QUANTILE 2 {property} {quantile} | Return the value of a numeric property at a given quantile of the results. Quantile is expressed as a number between 0 and 1. |
TOLIST | REDUCE TOLIST 1 {property} | Merge all distinct values of a given property into a single array. |
FIRST_VALUE | REDUCE FIRST_VALUE {nargs} {property} [BY {property} [ASC|DESC]] | Return the first or top value of a given property in the group, optionally by comparing that or another property. |
RANDOM_SAMPLE | REDUCE RANDOM_SAMPLE {nargs} {property} {sample_size} | Perform a reservoir sampling of the group elements with a given size, and return an array of the sampled items with an even distribution. |
5.5 APPLY functions
Function | Description |
---|---|
log(x) | Return the logarithm of a number, property or sub-expression |
abs(x) | Return the absolute number of a numeric expression |
ceil(x) | Round to the smallest value not less than x |
floor(x) | Round to largest value not greater than x |
log2(x) | Return the logarithm of x to base 2 |
exp(x) | Return the exponent of x |
sqrt(x) | Return the square root of x |
Function | Description |
---|---|
upper(s) | Return the uppercase conversion of s |
lower(s) | Return the lowercase conversion of s |
substr(s, offset, count) | Return the substring of s, starting at offset and having count characters. If offset is negative, it represents the distance from the end of the string. If count is -1, it means "the rest of the string starting at offset". |
format( fmt, ...) | Use the arguments following fmt to format a string. Currently the only format argument supported is %s and it applies to all types of arguments. |
matched_terms([max_terms=100]) | Return the query terms that matched for each record (up to 100), as a list. If a limit is specified, we will return the first N matches we find - based on query order. |
split(s, [sep=","], [strip=" "]) | Split a string by any character in the string sep, and strip any characters in strip. If only s is specified, we split by commas and strip spaces. The output is an array. |
Function | Description |
---|---|
timefmt(x, [fmt]) | Return a formatted time string based on a numeric timestamp value x. |
parsetime(timesharing, [fmt]) | The opposite of timefmt() - parse a time format using a given format string. |
day(timestamp) | Round a Unix timestamp to midnight (00:00) start of the current day. |
hour(timestamp) | Round a Unix timestamp to the beginning of the current hour. |
minute(timestamp) | Round a Unix timestamp to the beginning of the current minute. |
month(timestamp) | Round a unix timestamp to the beginning of the current month. |
dayofweek(timestamp) | Convert a Unix timestamp to the day number (Sunday = 0). |
dayofmonth(timestamp) | Convert a Unix timestamp to the day of month number (1 .. 31). |
dayofyear(timestamp) | Convert a Unix timestamp to the day of year number (0 .. 365). |
year(timestamp) | Convert a Unix timestamp to the current year (e.g. 2018). |
monthofyear(timestamp) | Convert a Unix timestamp to the current month (0 .. 11). |
6 Synonyms
Redis allows the use of synonym words for the searches. These synonyms are stored in a synonyms data structure. The synonym data structure is a set of gorups, with each gorup containing a list of words, which are synonyms. An example of such structure is:
{boy, child, baby} {girl, child, baby} {man, adult, person}
When searching in Redis with FT.SEARCH, any matching words in the synonym list will be returned as result, as well as the original word. Using the synonyms table the search of the term 'child', which is not in the table, gives:
Redis search using synonyms
FT.SEARCH table child
1) (integer) 2
2) "index1"
3) 1) "name"
2) "boy"
4) "index2"
5) 1) "name"
2) "girl"
As seen, when the synonyms data structure contains a given group of synonyms, performing a query will return any document that contains a synonym in the list.
6.1 Adding synonyms
In order to add synonyms to the index, the command FT.SYNADD is used. the syntax of this command is as follows:
FT.SYNADD <index name> <term1> <term2> ...
The command adds the given synonyms, passed on as individual strings, to the table (< index name>). It ouputs the index of the synonyms group, in order to use it later if the list wants to be updated.
It is to note that only the documents indexed after the addition of the synonyms will be affected by these. Therefore, a document added after will not be included in the search if synonyms want do be used.
Example of synonyms addition
FT.SYNADD table boy child baby
(integer) 0
6.2 Updating synonyms
Synonym groups can be updated with new words. Words cannot be removed from a synonym group. The command used to add new words to a synonyms group is FT.SYNUPDATE, as seen below.
FT.SYNUPDATE <index name> <synonym group id> <term1> <term2> ...
The command updates the according synonym group, adding the given words.
As with SYNADD, only the documents indexed after the addition of new words will be affected by these. This means that new words of the synonym group will only be taken into account for documents indexed after these new words are added to the synonyms group.
Example of synonyms update
FT.SYNADD table boy child baby FT.SYNUPDATE table 0 man
(integer) 0
OK
6.3 Viewing all the synonym groups
If one desires to see the synonym groups that are stored in the synonyms data structure at any given time, the commad FT.SYNDUMP can be used, as follows.
FT.SYNDUMP <index name>
The command returns a list of the separate synonym words, along with the respective group id, of all the synonym groups the word belongs to.
Example of synonyms dump
FT.SYNADD table boy child baby FT.SYNADD table girl child baby FT.SYNUPDATE table 0 man FT.SYNDUMP table
(integer) 0
(integer) 1
OK
1) "man"
2) 1) (integer) 0
3) "girl"
4) 1) (integer) 1
5) "baby"
6) 1) (integer) 0
2) (integer) 1
7) "child"
8) 1) (integer) 0
2) (integer) 1
9) "boy"
10) 1) (integer) 0
7 RediSearch useful commands
7.1 What RediSearch stores in Redis
As RediSearch's module uses Redis' key-value structure, it must store all the information of the Indexes
and the Suggestions
in a key-value pair. In this section, we will
try to understand how RediSearch stores the information.
First, create a new index in RediSearch:
FT.CREATE deister_cars SCHEMA model TEXT power NUMERIC
Now use the command keys to obtain if RediSearch has stored a new key in Redis.
KEYS *deister_cars*
1) "idx:deister_cars"
RediSearch has stored a key idx:deister_cars for the newly created index.
If the type of this key is inspected we can see the following:
TYPE idx:deister_cars
ft_index0
As we can see, the type of the value is a ft_index0
. This type is not a native type, and is imported from the RediSearch module. Therefore, the value of this key must never be changed manually.
Now let's store a new car in the index:
FT.ADD deister_cars deisterCar1 1.0 FIELDS model Tesla power 170
And search for what keys Redis has created for this new entry in the index.
KEYS *
1) "idx:deister_cars"
2) "ft:deister_cars/tesla"
3) "nm:deister_cars/power"
4) "deisterCar1"
Now RediSearch has created three new keys for a single document!
If one takes a look into the types of these keys:
127.0.0.1:6379> type ft:deister_cars/tesla ft_invidx 127.0.0.1:6379> type nm:deister_cars/power numericdx 127.0.0.1:6379> type deisterCar1 hash
The types of the keys prefixed with ft and nm are ft_invidx
and numericdx
. Once again, these types are not native types and Redis cannot read them using GET, HGET, SGET... These types are compressed metadata information
about the document that we just stored.
However, the key deisterCar1 is of hash type. This type of value can be read by Redis!. Let's read the value using the command HGETALL.
127.0.0.1:6379> HGETALL deisterCar1
1) "model"
2) "Tesla"
3) "power"
4) "170"
RediSearch has stored in a hash key-value pair the information of the document.
7.2 Listing all existing indexes in Redis
Now that we know what RediSearch stores in Redis when we create a new index, we can use this information to get a list of all existing indexes.
Using FT._LIST
Using KEYS
.
Since we know that Redis stores all indexes as idx:.... we can use this to get a list of all existing indexes with:
KEYS idx:*
This will output a list of all keys containing idx:* in the name, and therefore a list of all our indexes.