The RedisJSON module allows you to store JSON documents directly in Redis, and RediSearch lets you index and query those JSON documents with a powerful search engine.

Let’s see it in action. Imagine you’re building a catalog for an online store. Each product is a JSON document.

{
  "id": "prod123",
  "name": "Super Widget",
  "description": "A high-quality widget for all your needs.",
  "price": 29.99,
  "stock": 150,
  "tags": ["electronics", "gadget", "new"],
  "manufacturer": {
    "name": "Acme Corp",
    "country": "USA"
  }
}

You can store this directly in Redis using the JSON.SET command:

redis-cli> JSON.SET products:prod123 $ '{"id": "prod123", "name": "Super Widget", "description": "A high-quality widget for all your needs.", "price": 29.99, "stock": 150, "tags": ["electronics", "gadget", "new"], "manufacturer": {"name": "Acme Corp", "country": "USA"}}'

Now, to make this searchable, you’d use RediSearch. First, create an index. You’ll define which fields within your JSON documents you want to index and how.

redis-cli> FT.CREATE idx:products ON JSON PREFIX 1 products: SCHEMA $.name AS name TEXT $.description AS description TEXT $.price AS price NUMERIC $.stock AS stock NUMERIC $.tags AS tags TAG $.manufacturer.name AS manufacturer_name TEXT

This FT.CREATE command tells RediSearch:

  • idx:products: The name of your index.
  • ON JSON: We’re indexing JSON documents.
  • PREFIX 1 products:: The keys in Redis that belong to this index start with products:.
  • SCHEMA ...: This is where you define how to extract and index fields from your JSON.
    • $.name AS name TEXT: Index the name field at the JSON root ($) as a TEXT field for full-text search.
    • $.price AS price NUMERIC: Index price as a NUMERIC field for range queries.
    • $.tags AS tags TAG: Index tags as a TAG field for exact matching (e.g., finding all products tagged "electronics").
    • $.manufacturer.name AS manufacturer_name TEXT: Index nested fields like the manufacturer’s name.

Once the index is created and your documents are stored, you can query them.

To find all products named "Super Widget":

redis-cli> FT.SEARCH idx:products '@name:"Super Widget"'

To find all products costing less than $30:

redis-cli> FT.SEARCH idx:products '@price:[-inf (30]'

To find products tagged "gadget" and manufactured in "USA":

redis-cli> FT.SEARCH idx:products '@tags:gadget @manufacturer.country:USA'

The power here is that RedisJSON allows granular access to JSON elements. You can update a single field without replacing the entire document. For example, to update the stock of prod123:

redis-cli> JSON.SET products:prod123 '$.stock' 145

RediSearch automatically picks up this change and updates its index. You can also retrieve specific parts of a JSON document using JSONPath within your search results.

For example, to get just the names of products tagged "electronics":

redis-cli> FT.SEARCH idx:products '@tags:electronics' RETURN 1 $.name AS product_name

This returns a list of results, where each result contains a product_name field with the value from the $.name path of the matching JSON document.

The RediSearch query parser is quite flexible. You can use boolean operators like AND, OR, NOT, and fuzzy matching for text fields. For numeric fields, you can specify ranges. Tag fields allow for efficient filtering based on exact string matches.

The ON JSON directive in FT.CREATE is crucial. It tells RediSearch to interpret the Redis value as a JSON document and use the provided JSONPaths to extract fields for indexing. Without it, RediSearch would treat the entire JSON string as a single blob of text.

When you define a TAG field, RediSearch internally creates a set of unique terms for that field. This is highly efficient for filtering. For NUMERIC fields, it uses a sorted set structure allowing for fast range queries. TEXT fields use inverted indexes, supporting full-text search capabilities.

One of the most powerful features is the ability to query and return specific JSONPaths directly from the search results. For instance, if you only need the id and price of products matching a query, you can specify that in the RETURN clause:

redis-cli> FT.SEARCH idx:products '@tags:gadget' RETURN 2 $.id AS id $.price AS price

This is significantly more efficient than fetching the entire JSON document and then parsing it client-side, especially for large documents or when performing many queries. It leverages Redis’s ability to perform operations directly on the data structures.

The ability to combine Redis’s speed and data structures with a rich query language makes this combination incredibly potent for applications needing to store and search structured or semi-structured data.

The next step is often exploring how to handle complex aggregations or geospatial queries on your JSON documents.

Want structured learning?

Take the full Redis course →