Table of contents
1.
Introduction
2.
Prerequisites required
3.
How to index JSON documents
4.
Adding a JSON document to the index 
5.
Searching
6.
Field projection
6.1.
Projecting using JSON Path expressions 
6.2.
Highlighting 
7.
Aggregation with JSON Path expression
8.
Current indexing limitations 
8.1.
Indexing JSON objects is not possible.
8.2.
Index JSON numbers and  strings as NUMERI and TEXT 
8.3.
SORTABLE is not supported on TAG
9.
Frequently Asked Questions
9.1.
Can we store JSON data in Redis?
9.2.
What is index in Redis?
9.3.
How to use the Redis command line?
10.
Conclusion
Last Updated: Mar 27, 2024

Indexing JSON in RediSearch

Author GAZAL ARORA
0 upvote

Introduction

RediSearch is a source available Redis module that adds query ability, secondary indexing, and full-text search to the database. These features enable multi-field queries, aggregation, exact phrase matching, and numeric filtering for text queries.

RediSearch indexes JSON as well. The RedisJSON module is required to index JSON.

Prerequisites required

  • Redis 6.x or later
  • RedisJSON 2.0 or later
  • RediSearch 2.2 or later

How to index JSON documents

You can now tell RediSearch that you wish to index JSON documents by specifying ON JSON.

You can use JSONPath expressions in the SCHEMA. Each JSON Path expression's result is indexed and assigned a logical name (attribute). This attribute, earlier called field, is used in the query.

The basic syntax for indexing a JSON document is as follows:

FT.CREATE {name_of_index} ON JSON SCHEMA {json_path} AS {attribute} {type}

Adding a JSON document to the index 

Any pre-existing JSON document and any new or modified JSON document are immediately indexed once the index is created.

Any pre-existing JSON document and any new or modified JSON document are immediately indexed once the index is created.

Any write command from the RedisJSON module can be used (JSON.SET, JSON.ARRAPPEND, etc.).

The following JSON document is used in this example:

{
  "user": {
    "name": "Johnas",
    "tag": "foo,bar",
    "hp": "1000",
    "dmg": "150"
  }
}

To save the document in the database, use JSON.SET:

JSON.SET myDoc $ '{"user":{"name":"Johnas","tag":"foo,bar","hp":1000, "dmg":150}}'

The page will be visible on the index as soon as the JSON.SET call returns since indexing are synchronous. Any subsequent query that returns the document matches the indexed content.

Searching

Use the FT.SEARCH commands to find documents. Any attribute defined in the SCHEMA can be searched.

For example, find the user named Johnas:

FT.SEARCH userIdx '@name:(Johnas)'
1) (integer) 1
2) "myDoc"
3) 1) "$"
   2) "{\"user\":{\"name\":\"Johnas\",\"tag\":\"foo,bar\",\"hp\":1000,\"dmg\":150}}"

Field projection

By default, FT.SEARCH returns the entire document.

You can also retrieve only one attribute (for example, name):

FT.SEARCH userIdx '@name:(Johnas)' RETURN 1 name
1) (integer) 1
2) "myDoc"
3) 1) "name"
   2) "\"Johnas\""

Projecting using JSON Path expressions 

A JSON Path expression can be used with the RETURN parameter to extract any part of the JSON document.

The result of the JSON Path expression $.user.hp is returned in the following example.

FT.SEARCH userIdx '@name:(Johnas)' RETURN 1 $.user.hp
1) (integer) 1
2) "myDoc"
3) 1) "$.user.hp"
   2) "1000"

Note that the property name is actually the JSON expression: 3) 1) "$.user.hp"

Highlighting 

Using the TEXT type, you can highlight any attribute as soon as it is indexed. You must explicitly set the property in the RETURN and HIGHLIGHT arguments for FT.SEARCH.

FT.SEARCH userIdx '@name:(Johnas)' RETURN 1 name HIGHLIGHT FIELDS 1 name TAGS '<b>' '</b>'
1) (integer) 1
2) "myDoc"
3) 1) "name"
   2) "\"<b>Johnas\""

Aggregation with JSON Path expression

Aggregation is a handy feature. It can be used to create facet queries or generate statistics. JSON Path expressions are accepted in the LOAD parameter. In the pipeline, any value (including non-indexed) can be used.

This example uses a simple method to load two numeric values from a JSON document.

FT.AGGREGATE userIdx '*' LOAD 6 $.user.hp AS hp $.user.dmg AS dmg APPLY '@hp-@dmg' AS points
1) (integer) 1
2) 1) "point"
   2) "850"

Current indexing limitations 

SON arrays can be indexed only in a TAG field. You can only index an array of strings or booleans in a TAG field. Numeric, geo and null types are not supported.

Indexing JSON objects is not possible.

A JSONPath expression should return a single scalar value indexed (string or number). The JSONPath expression will be ignored if it produces an object. However, the strings can be indexed in separate attributes.

Given the following data:

{
  "name": "quarters",
  "address": [
    "Suite 50",
    "River View"
  ],
  "cp": "CA 9404"
}

You must first construct two fields before you can index the array under the address key:

FT.CREATE orgIdx ON JSON SCHEMA $.address[0] AS a1 TEXT $.address[1] AS a2 TEXT
OK

The document can now be indexed:

JSON.SET org:1 $ '{"name": "Headquarters","address": ["Suite 250","Mountain View"],"cp": "CA 94040"}'
OK

You can now also search in the address:

FT.SEARCH orgIdx "suite 50"
1) (integer) 1
2) "org:1"
3) 1) "$"
   2) "{\"name\":\"quarters\",\"address\":[\"Suite 50\",\"River View\"],\"cp\":\"CA 9404\"}"

Index JSON numbers and  strings as NUMERI and TEXT 

  • JSON strings can only be indexed as TEXT, TAG, or GEO (using the right syntax).
  • Only NUMERIC can be used to index JSON numbers.
  • NULL and Boolean values are ignored.

SORTABLE is not supported on TAG

FT.CREATE orgIdx ON JSON SCHEMA $.cp[0] AS cp TAG SORTABLE

(error) On JSON, cannot set tag field to sortable - cp

SORTABLE (as a side effect) can be used with hashes to increase the performance of FT.AGGREGATE on TAGs. Because the hash value is a string, such as "foo, bar," this is possible.

You can index an array of strings using JSON. RediSearch has no idea how to order the result because there is no valid single textual representation of those data.

Frequently Asked Questions

Can we store JSON data in Redis?

JSON can be stored in redis as a string in a dedicated key (or as a member/value of a set/list) or as a hash structure. If you look at the Friendlier hash commands section of the node redis docs, you'll notice that it provides some useful methods for processing JSON-based data.

What is index in Redis?

The key-value database model is the foundation of Redis. Every piece of data is either directly or indirectly linked to a key. If you wish to access data based on something other than the key, you'll need to create an index that uses one of Redis' multiple data types.

How to use the Redis command line?

To launch the Redis client, open a terminal and type redis-cli. This will establish a connection to your local server, from which you can issue any command. We connect to a Redis server running on the local machine and run the command PING to see if the server is up and running.

Conclusion

In this article, we learned about Indexing JSON in RediSearch. 

JSON can be stored in redis as a string in a dedicated key (or as a member/value of a set/list) or as a hash structure. If you wish to access data based on something other than the key, you'll need to create an index that uses one of Redis' multiple data types. RediSearch indexes JSON as well. The RedisJSON module is required to index JSON.

We then looked at some methods available to manipulate or work with indexed JSON data.

Click here to know about RedisGraph or RedisCLI.

You can use Coding Ninjas Studio to practice various DSA questions asked in different interviews. It will assist you in mastering effective coding techniques, and you will also get interview experiences with people working in big companies.

Happy Learning!!

Live masterclass