Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QueryByExample<T> with RedisEnhancedRepository<T, ID> #439

Closed
dasivon021 opened this issue May 16, 2024 · 4 comments · Fixed by #441
Closed

QueryByExample<T> with RedisEnhancedRepository<T, ID> #439

dasivon021 opened this issue May 16, 2024 · 4 comments · Fixed by #441

Comments

@dasivon021
Copy link

dasivon021 commented May 16, 2024

Hi @bsbodden and @sazzad16,

When I'm trying to execute query using QueryByExampleExecutor<T> interface special characters are not escaped which causes query to fail. Reproducible example is here

Context:

I'm using Spring Boot 3.2.3 and redis-om-spring (0.9.1). redis-om-spring transitively uses spring-data-redis. The model looks like this:

@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@org.springframework.data.redis.core.RedisHash
public class Student {

    @Id
    private Long id;

    @com.redis.om.spring.annotations.Indexed(alias = "User-Name")
    private String userName;

    @com.redis.om.spring.annotations.Indexed(alias = "Event-Timestamp")
    private LocalDateTime eventTimestamp;
    
}

Hash records are stored in this format:

com.example.demo.entity.Student:123214

  "First-Name": "UWucCgR+GAiakfbSpzuLBQ==",
  "Event-Timestamp": "182952385124",
  "User-Name": "marc.mk"

My application will only be executing search queries.

On the application start up, index is created like this:

FT.CREATE" "com.example.demo.entity.StudentIdx" "ON" "HASH" "PREFIX" "1" "com.example.demo.entity.Student:" "SCHEMA" "userName" "AS" "User-Name" "TAG" "SEPARATOR" "|" "eventTimestamp" "AS" "Event-Timestamp" "NUMERIC" "id" "AS" "id" "NUMERIC" "SORTABLE"

Repository:

@Repository
@Transactional(readOnly = true)
public interface StudentRepository extends RedisEnhancedRepository<Student, Long>, QueryByExampleExecutor<Student> {

    List<Student> findByUserNameAndEventTimestampBetweenOrderByEventTimestampAsc(String userName, String fromDate, String toDate);

    List<Student> findByUserName(String userName);

    default Student findFirstByPropertyOrderByEventTimestamp(
            Student student,
            ExampleMatcher exampleMatcher,
            Function<FluentQuery.FetchableFluentQuery<Student>, Student> queryFunction) {
        return findBy(Example.of(student, exampleMatcher), queryFunction);
    }
}

If I try to invoke findFirstByPropertyOrderByEventTimestamp, I get an exception:

redis.clients.jedis.exceptions.JedisDataException: Syntax error at offset 7 near User
	at redis.clients.jedis.Protocol.processError(Protocol.java:105) ~[jedis-5.0.2.jar:na]

By looking at the queries on monitor, I can see this is actually executed:

"FT.SEARCH" "com.example.demo.entity.StudentIdx" "( @User-Name:{pera})" "SORTBY" "Event-Timestamp" "DESC" "LIMIT" "0" "1" "DIALECT" "1"

What in fact should be executed is:

"FT.SEARCH" "com.example.demo.entity.StudentIdx" "( @User\\-Name:{pera})" "SORTBY" "Event-Timestamp" "DESC" "LIMIT" "0" "1" "DIALECT" "1"

This is the code which invokes the query:

Function<FluentQuery.FetchableFluentQuery<Student>, Student> sortFunction =
				query -> query.sortBy(Sort.by("Event-Timestamp").descending()).firstValue();

var matcher =ExampleMatcher.matching().withMatcher("userName", ExampleMatcher.GenericPropertyMatcher::exact);

var student = Student.builder().userName("pera").build();

Student result = studentRepository.findFirstByPropertyOrderByEventTimestamp(student, matcher, sortFunction);

This same problem was present in redis-om-spring lib, but with 433 it was quickly resolved.

Hopefully, similar changes are can be done here.

@dasivon021 dasivon021 changed the title QueryByExample<T> with EnhancedRepository<T, ID> QueryByExample<T> with RedisEnhancedRepository<T, ID> May 16, 2024
@bsbodden
Copy link
Contributor

@dasivon021 can you copy and paste the ticket description form the Spring Data Redis repo here?

@dasivon021
Copy link
Author

done.

@dasivon021
Copy link
Author

Hi @bsbodden, I just tested with 0.9.2-SNAPSHOT and property (alias name) is properly escaped
"FT.SEARCH" "myIndexStudent" "( @User\\-Name:{pera})" "SORTBY" "Event-Timestamp" "DESC" "LIMIT" "0" "1" "DIALECT" "1"

But it does not escape values with special characters. If in the initial post, you use this line:

var student = Student.builder().userName("100-64.3.22").build();

The query which is issued is:

"FT.SEARCH" "myIndexStudent" "( @User\\-Name:{100-64.3.22})" "SORTBY" "Event-Timestamp" "DESC" "LIMIT" "0" "1" "DIALECT" "1"

Two questions:

  1. Shouldn't query look like this:

"FT.SEARCH" "myIndexStudent" "( @User\\-Name:{100\\-64\\.3\\.22})" "SORTBY" "Event-Timestamp" "DESC" "LIMIT" "0" "1" "DIALECT" "1"

  1. Why in this query ( and ) are used? Is this some Redis thing or just how spring-data-redis generates query?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants