Skip to content

Commit 99aa008

Browse files
committed
docs: correct hash-mappings documentation
Fix documentation that incorrectly described Redis OM Spring hash mapping as using Spring Data Redis' basic Set-based indexing. Redis OM Spring actually creates RediSearch indexes using FT.CREATE commands for Hash entities. Key corrections: - Clarify that Redis OM Spring uses RediSearch indexes, not Redis Sets - Add comparison table showing differences from Spring Data Redis - Show actual Redis commands (FT.CREATE ON HASH) generated - Explain O(log N) index-based query performance vs O(N) scans - Add migration guide from Spring Data Redis - Update examples to show RediSearch field types (TEXT, TAG, NUMERIC, GEO, VECTOR)
1 parent 3d8b53f commit 99aa008

File tree

1 file changed

+203
-41
lines changed

1 file changed

+203
-41
lines changed

docs/content/modules/ROOT/pages/hash-mappings.adoc

Lines changed: 203 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,61 @@
11
[[hash.mappings]]
2-
= Redis Hash Mappings
2+
= Redis Hash Mappings with RediSearch
33
:page-toclevels: 3
44
:experimental:
55
:source-highlighter: highlight.js
66

77
== Introduction
88

9-
Spring Data Redis (SDR), the library that Redis OM Spring extends, provides mapping of Spring Entities to Redis Hashes. Redis OM Spring enhances this capability by integrating with the Query Engine available in Redis 8.0.0+ (or via Redis Stack for older versions).
9+
Redis OM Spring fundamentally transforms how Redis Hashes work by adding RediSearch indexing capabilities on top of the standard hash storage. This is a key distinction from Spring Data Redis, which only provides basic hash operations.
1010

11-
This integration brings powerful search and indexing capabilities to Redis Hashes, while maintaining compatibility with existing Spring Data Redis code.
11+
=== The Core Difference
1212

13-
== Key Benefits of Redis OM Spring Hash Mapping
13+
**Spring Data Redis**: Stores entities as Redis Hashes with basic secondary indexing using Redis Sets
14+
**Redis OM Spring**: Stores entities as Redis Hashes PLUS creates RediSearch indexes for powerful querying
1415

15-
* **Enhanced Query Capabilities**: Full text search, numeric ranges, geo-spatial queries
16-
* **Backward Compatibility**: Works with existing Spring Data Redis code
17-
* **Simple Annotations**: Easy to add indexing without changing your data model
18-
* **Performance**: Efficient storage format for simple objects
16+
[source,bash]
17+
----
18+
# Spring Data Redis approach (basic)
19+
HSET person:123 name "John" email "[email protected]" # Store hash
20+
SADD person:name:John person:123 # Basic index
21+
22+
# Redis OM Spring approach (enhanced)
23+
HSET person:123 name "John" email "[email protected]" # Store hash (same)
24+
FT.CREATE PersonIdx ON HASH ... # RediSearch index (NEW!)
25+
----
26+
27+
Redis OM Spring creates full RediSearch indexes using `FT.CREATE` commands, providing:
28+
29+
== Key Differences from Spring Data Redis
30+
31+
[cols="1,2,2"]
32+
|===
33+
|Feature |Spring Data Redis |Redis OM Spring
34+
35+
|Indexing Mechanism
36+
|Redis Sets for @Indexed fields
37+
|RediSearch indexes via FT.CREATE
38+
39+
|Query Performance
40+
|O(N) scans for complex queries
41+
|O(log N) index-based queries
42+
43+
|Search Capabilities
44+
|Basic equality checks only
45+
|Full-text search, ranges, aggregations
46+
47+
|Field Types
48+
|Simple hash fields
49+
|TEXT, TAG, NUMERIC, GEO, VECTOR fields
50+
51+
|Repository Type
52+
|CrudRepository/RedisRepository
53+
|RedisEnhancedRepository
54+
55+
|Query Methods
56+
|Limited to findBy patterns
57+
|Complex queries, @Query, Entity Streams
58+
|===
1959

2060
== Basic Usage
2161

@@ -167,9 +207,9 @@ found.ifPresent(person -> {
167207
repository.deleteById(newPerson.getId());
168208
----
169209

170-
== How Redis OM Spring Stores Redis Hashes
210+
== How Data is Stored and Indexed
171211

172-
Redis Hashes are flat key-value structures. When storing Java objects, Redis OM Spring follows these mapping rules:
212+
Redis OM Spring stores data in standard Redis Hashes (just like Spring Data Redis) but additionally creates RediSearch indexes for querying:
173213

174214
=== Object-to-Hash Mapping
175215

@@ -207,25 +247,39 @@ Redis Hashes are flat key-value structures. When storing Java objects, Redis OM
207247
|`addresses.[0].city = "Tear"`
208248
|===
209249

210-
Additionally, Redis OM Spring adds a `_class` attribute to store type information:
250+
The data is stored in a standard Redis Hash:
211251

212252
[source,text]
213253
----
214-
_class = com.example.Person
215-
id = 01HXYZ123ABC
216-
name = Mat Cauthon
217-
218-
roles.[0] = general
219-
roles.[1] = gambler
220-
address.city = Tear
221-
address.street = High Street
222-
----
254+
# Standard Redis Hash (same as Spring Data Redis)
255+
HSET people:01HXYZ123ABC
256+
_class "com.example.Person"
257+
id "01HXYZ123ABC"
258+
name "Mat Cauthon"
259+
260+
roles.[0] "general"
261+
roles.[1] "gambler"
262+
address.city "Tear"
263+
address.street "High Street"
264+
265+
# But Redis OM Spring ALSO creates a RediSearch index
266+
FT.CREATE PersonIdx ON HASH PREFIX 1 people: SCHEMA
267+
name TAG SORTABLE
268+
email TEXT
269+
roles TAG SEPARATOR |
270+
address.city TAG
271+
----
272+
273+
This dual approach means:
274+
- Your data remains compatible with Spring Data Redis
275+
- You get powerful search capabilities through RediSearch
276+
- Queries use the index for performance, not scanning
223277

224278
== Indexing and Searching
225279

226-
=== Simple Property Indexes
280+
=== How Redis OM Spring Creates Indexes
227281

228-
Use the `@Indexed` annotation to create secondary indexes for fields:
282+
When you annotate fields with `@Indexed`, Redis OM Spring creates a RediSearch index:
229283

230284
[source,java]
231285
----
@@ -234,25 +288,32 @@ public class Person {
234288
@Id
235289
private String id;
236290
237-
@Indexed
291+
@Indexed // Creates a TAG field in RediSearch
238292
private String name;
239293
240-
@Indexed
294+
@Searchable // Creates a TEXT field for full-text search
241295
private String email;
296+
297+
@Indexed // Creates a TAG field for set values
298+
private Set<String> roles;
242299
}
243300
----
244301

245-
This creates Redis Sets for each value:
302+
This generates a RediSearch index creation command:
246303

247304
[source,text]
248305
----
249-
SADD people:name:Mat people:01HXYZ123ABC
250-
SADD people:email:[email protected] people:01HXYZ123ABC
306+
FT.CREATE PersonIdx ON HASH PREFIX 1 people: SCHEMA
307+
name TAG SORTABLE
308+
email TEXT
309+
roles TAG SEPARATOR |
251310
----
252311

253-
=== Geospatial Indexes
312+
NOTE: This is fundamentally different from Spring Data Redis, which would only create Redis Sets for indexed fields.
254313

255-
For location-based queries, use the `@Indexed` annotation on Point fields:
314+
=== Advanced Field Types
315+
316+
Redis OM Spring supports specialized field types through RediSearch:
256317

257318
[source,java]
258319
----
@@ -261,19 +322,33 @@ public class Company {
261322
@Id
262323
private String id;
263324
264-
@Indexed
325+
@Indexed // Creates a GEO field in RediSearch
265326
private Point location;
266327
267-
@Searchable(sortable = true)
328+
@Searchable(sortable = true) // Creates a TEXT field with SORTABLE
268329
private String name;
330+
331+
@NumericIndexed // Creates a NUMERIC field for range queries
332+
private Integer yearFounded;
333+
334+
@TagIndexed // Creates a TAG field for exact matches
335+
private Set<String> categories;
336+
337+
@VectorIndexed(algorithm = VectorAlgorithm.HNSW) // Vector similarity search
338+
private byte[] embedding;
269339
}
270340
----
271341

272-
This enables geo-spatial queries:
342+
The RediSearch index supports complex queries on these fields:
273343

274344
[source,text]
275345
----
276-
GEOADD CompanyIdx:location 13.361389 38.115556 Company:01HXYZ123ABC
346+
FT.CREATE CompanyIdx ON HASH PREFIX 1 Company: SCHEMA
347+
location GEO
348+
name TEXT SORTABLE
349+
yearFounded NUMERIC SORTABLE
350+
categories TAG SEPARATOR |
351+
embedding VECTOR HNSW 6 DIM 768 DISTANCE_METRIC COSINE
277352
----
278353

279354
=== Query Methods
@@ -306,6 +381,50 @@ public interface PersonRepository extends RedisEnhancedRepository<Person, String
306381

307382
For detailed query capabilities, see the xref:repository-queries.adoc[Repository Query Methods] section.
308383

384+
== RediSearch Integration
385+
386+
Redis OM Spring automatically manages RediSearch indexes for your hash entities:
387+
388+
=== Index Creation
389+
390+
When your application starts, Redis OM Spring:
391+
392+
1. Scans for `@RedisHash` annotated classes
393+
2. Identifies fields with indexing annotations (`@Indexed`, `@Searchable`, etc.)
394+
3. Creates RediSearch indexes using `FT.CREATE` commands
395+
4. Maintains index synchronization as entities are saved/deleted
396+
397+
=== Query Execution
398+
399+
Repository queries are translated to RediSearch queries:
400+
401+
[source,java]
402+
----
403+
// Repository method
404+
List<Person> findByNameAndRolesContaining(String name, String role);
405+
406+
// Translates to RediSearch query
407+
FT.SEARCH PersonIdx "@name:{John} @roles:{admin}"
408+
----
409+
410+
=== Entity Streams
411+
412+
Redis OM Spring provides a fluent API for complex queries:
413+
414+
[source,java]
415+
----
416+
@Autowired
417+
EntityStream entityStream;
418+
419+
// Complex query using Entity Streams
420+
List<Person> admins = entityStream
421+
.of(Person.class)
422+
.filter(Person$.ROLES.contains("admin"))
423+
.filter(Person$.NAME.startsWith("J"))
424+
.sorted(Person$.EMAIL, SortOrder.ASC)
425+
.collect(Collectors.toList());
426+
----
427+
309428
== Time To Live (TTL)
310429

311430
You can set expiration times for entities:
@@ -393,11 +512,40 @@ public class RedisConfig {
393512
}
394513
----
395514

396-
== Redis Cluster Considerations
515+
== Migration from Spring Data Redis
516+
517+
Migrating from Spring Data Redis to Redis OM Spring is straightforward:
397518

398-
When using Redis Cluster, it's important to ensure that related data is stored in the same hash slot to enable atomic operations and efficient queries.
519+
1. **Change the repository interface**:
520+
```java
521+
// Before: Spring Data Redis
522+
public interface PersonRepository extends CrudRepository<Person, String> { }
523+
524+
// After: Redis OM Spring
525+
public interface PersonRepository extends RedisEnhancedRepository<Person, String> { }
526+
```
399527

400-
Use the `@IdAsHashTag` annotation to ensure that keys for an entity and its indexes are stored in the same hash slot:
528+
2. **Enable enhanced repositories**:
529+
```java
530+
// Before
531+
@EnableRedisRepositories
532+
533+
// After
534+
@EnableRedisEnhancedRepositories
535+
```
536+
537+
3. **Add indexing annotations** (optional but recommended):
538+
```java
539+
@Indexed // For exact matches
540+
@Searchable // For full-text search
541+
@NumericIndexed // For numeric ranges
542+
```
543+
544+
Your existing data remains compatible, and you immediately gain access to powerful search capabilities.
545+
546+
== Redis Cluster Considerations
547+
548+
When using Redis Cluster with RediSearch indexes, use the `@IdAsHashTag` annotation to ensure proper data locality:
401549

402550
[source,java]
403551
----
@@ -415,14 +563,28 @@ public class HashWithHashTagId {
415563

416564
== Performance Considerations
417565

418-
* Redis Hashes are very efficient for simple data structures
419-
* Each query operation requires multiple Redis commands (index lookup + hash retrieval)
420-
* For complex nested objects, consider using xref:json_mappings.adoc[Redis JSON] instead
421-
* Writing objects to a Redis hash deletes and re-creates the whole hash, so data not mapped is lost
566+
* **Index-based queries**: Redis OM Spring uses RediSearch indexes, providing O(log N) query performance vs O(N) scans in Spring Data Redis
567+
* **Storage efficiency**: Data is still stored as standard Redis Hashes, maintaining the same memory efficiency
568+
* **Index overhead**: RediSearch indexes add some memory overhead but enable dramatic query performance improvements
569+
* **Complex objects**: For deeply nested structures, consider xref:json_mappings.adoc[Redis JSON] documents
570+
* **Write behavior**: Updates replace the entire hash (same as Spring Data Redis), unmapped data is lost
571+
572+
== Summary
573+
574+
Redis OM Spring enhances Redis Hash entities with RediSearch indexing, providing:
575+
576+
* **Full compatibility** with Spring Data Redis hash storage
577+
* **Powerful search capabilities** through RediSearch indexes
578+
* **O(log N) query performance** instead of O(N) scans
579+
* **Rich query methods** including full-text search, ranges, and aggregations
580+
* **Advanced field types** like vectors, geo-spatial, and more
581+
582+
The key takeaway: Redis OM Spring doesn't change how hashes are stored, it adds a powerful search layer on top.
422583

423584
== Next Steps
424585

425586
* xref:json_mappings.adoc[Redis JSON Mappings] - Compare with JSON document mapping
426587
* xref:repository-queries.adoc[Repository Query Methods] - Learn about query capabilities
427588
* xref:entity-streams.adoc[Entity Streams] - Explore fluent query API
428-
* xref:search.adoc[Redis Query Engine Integration] - Understand the search capabilities
589+
* xref:search.adoc[Redis Query Engine Integration] - Understand the search capabilities
590+
* xref:index-annotations.adoc[Index Annotations] - Deep dive into indexing options

0 commit comments

Comments
 (0)