spring-projects / spring-projects/spring-data-redis

Executing full-text queries by using Redis template

Open
#2,908 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

for: team-attention status: waiting-for-triage
Dominant language
Java
Stars
1.9k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

Hi,

Context:

I have a Spring Boot 3.2.3 app which uses spring-boot-starter-data-redis. We have a Redis cluster on the cloud, where RediSearch module is installed and where other applications are doing inserts of hash records. My application will only be executing search queries and have read-only permission towards cluster. So index already exist and I need to find a way to use it within my full-text queries but relaying on spring-boot-starter-data-redis since redis-om-spring has currently few issues which are blocking usage of pre-created index (#437, #438 & #439).

So pre-created index is created like this:

"FT.CREATE" "company:idx" "ON" "HASH" "PREFIX" "1" "session:" "SCHEMA" "User-Name" "TAG" "SEPARATOR" "|" "Event-Timestamp" "NUMERIC" "SORTABLE"

  1. Using Jedis (by excluding it from starter and adding jedis to pom):

Defining a template:

  @Bean
    public RedisTemplate<Long, Student> redisTemplate(RedisConnectionFactory connectionFactory) {
        var template = new RedisTemplate<Long, Student>();
        template.setConnectionFactory(connectionFactory);
        template.setEnableTransactionSupport(true);
        return template;
    }

Using it:

@GetMapping("/get")
public String getEntity(){
  Object o = executeCommand("FT.SEARCH", "comapany:idx".getBytes(), "@User\\-Name{pera}".getBytes(), "SORTBY".getBytes(), "Event-Timestamp".getBytes(), "DESC".getBytes(), "LIMIT".getBytes(), "0".getBytes(), "1".getBytes());
               
  System.out.println(o);
  return "a";
}

public Object executeCommand(String command, byte[]... parts) {
  return redisTemplate.execute(connection ->
	connection.execute(command, parts), false
  );
}

If I were to execute above query in redis-cli, the output would be:

1) (integer) 1
2) "student:abc"
3)  1) "User-Name""
    2) "pera"
     ..key-value pairs

But in code I get a List with bytes, which I don't like and there could be potential performance issues when doing (de)serialization. The problem with connection.execute is that returns byte[]
Screenshot_12

Question 1:
Is there a more optimal way to do issue these types of queries?

Question 2:
Is there a way to configure Redis template so when it issues these types of queries to return a list of entities instead of raw bytes?

  1. Using Lettuce (starter default):
java.lang.UnsupportedOperationException: io.lettuce.core.output.ByteArrayOutput does not support set(long)
	at io.lettuce.core.output.CommandOutput.set(CommandOutput.java:107) ~[lettuce-core-6.3.1.RELEASE.jar:6.3.1.RELEASE/12e6995]

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the RedisTemplate.execute and connection.execute usage shown in the issue, then inspect the Lettuce ByteArrayOutput exception. The issue mentions no repository files or tests. Done would require a documented or supported way to execute RediSearch queries through the template, handle results without unwanted raw-byte handling, and address the reported Lettuce failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, redis, spring-boot
Domain
backend, database
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.