Skip to content

Commit

Permalink
feature: add ability to use custom index names with @RedisHash annota…
Browse files Browse the repository at this point in the history
…ted entities via @IndexingOptions
  • Loading branch information
bsbodden committed May 21, 2024
1 parent 7205e1c commit bf11e3f
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface IndexingOptions {
String indexName() default "";
IndexCreationMode creationMode() default IndexCreationMode.SKIP_IF_EXIST;
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,20 @@ public void createIndexFor(Class<?> cl) {
Optional<String> maybeScoreField;
try {
if (isDocument) {
indexName = document.get().indexName();
// IndexingOptions overrides Document#
if (maybeIndexingOptions.isPresent()) {
indexName = maybeIndexingOptions.get().indexName();
} else {
indexName = document.get().indexName();
}
indexName = indexName.isBlank() ? cl.getName() + "Idx" : indexName;
} else {
indexName = cl.getName() + "Idx";
if (maybeIndexingOptions.isPresent()) {
indexName = maybeIndexingOptions.get().indexName();
indexName = indexName.isBlank() ? cl.getName() + "Idx" : indexName;
} else {
indexName = cl.getName() + "Idx";
}
}

logger.info(String.format("Found @%s annotated class: %s", idxType, cl.getName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.redis.om.spring.fixtures.hash.model.*;
import com.redis.om.spring.fixtures.hash.repository.*;
import com.redis.om.spring.repository.query.QueryUtils;
import com.redis.om.spring.search.stream.EntityStream;
import org.assertj.core.util.Arrays;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -15,7 +16,10 @@
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
import redis.clients.jedis.JedisPooled;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.search.aggr.AggregationResult;

import java.time.Duration;
Expand Down Expand Up @@ -56,8 +60,22 @@ class BasicRedisHashMappingTest extends AbstractBaseEnhancedRedisTest {
@Autowired
StudentRepository studentRepository;

@Autowired
CustomIndexHashRepository customIndexHashRepository;

@Autowired
EntityStream es;

@Autowired
JedisConnectionFactory jedisConnectionFactory;

private UnifiedJedis jedis;

@BeforeEach
void createTestDataIfNeeded() {
jedis = new JedisPooled(Objects.requireNonNull(jedisConnectionFactory.getPoolConfig()),
jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort());

flushSearchIndexFor(Company.class);
flushSearchIndexFor(Person.class);
john = Person.of("John Cleese", "[email protected]", "john");
Expand Down Expand Up @@ -90,8 +108,7 @@ void createTestDataIfNeeded() {
studentRepository.deleteAll();
List<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
var student = Student.of("Student" + i, i != 2 ? LocalDateTime.now() : LocalDateTime.of(2023, 6, 1, 1, 1,
1));
var student = Student.of("Student" + i, i != 2 ? LocalDateTime.now() : LocalDateTime.of(2023, 6, 1, 1, 1, 1));
student.setId((long) i);
students.add(student);
}
Expand Down Expand Up @@ -672,12 +689,10 @@ void testFindByPropertyWithAliasWithHyphens() {

@Test
void testFindByPropertyWithAliasWithHyphensAndOrderBy() {
LocalDateTime beginLocalDateTime = LocalDateTime.of(2023, 1, 1, 1, 1,
1);
LocalDateTime endLocalDateTime = LocalDateTime.of(2023, 12, 1, 1, 1,
1);
List<Student> result = studentRepository.findByUserNameAndEventTimestampBetweenOrderByEventTimestampAsc("Student2", beginLocalDateTime,
endLocalDateTime);
LocalDateTime beginLocalDateTime = LocalDateTime.of(2023, 1, 1, 1, 1, 1);
LocalDateTime endLocalDateTime = LocalDateTime.of(2023, 12, 1, 1, 1, 1);
List<Student> result = studentRepository.findByUserNameAndEventTimestampBetweenOrderByEventTimestampAsc("Student2",
beginLocalDateTime, endLocalDateTime);

assertAll( //
() -> assertThat(result).hasSize(1), //
Expand All @@ -687,8 +702,8 @@ void testFindByPropertyWithAliasWithHyphensAndOrderBy() {

@Test
void testQBEWithAliasWithHyphensAndOrderBy() {
Function<FetchableFluentQuery<Student>, Student> sortFunction =
query -> query.sortBy(Sort.by("Event-Timestamp").descending()).firstValue();
Function<FetchableFluentQuery<Student>, Student> sortFunction = query -> query.sortBy(
Sort.by("Event-Timestamp").descending()).firstValue();

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

Expand All @@ -698,4 +713,32 @@ void testQBEWithAliasWithHyphensAndOrderBy() {
Student result = studentRepository.findFirstByPropertyOrderByEventTimestamp(student, matcher, sortFunction);
assertThat(result.getUserName()).isEqualTo("Student2");
}

//customIndexHashRepository

@Test
void testCustomIndexName() {
// CustomIndexHash is a Hash that has a custom index name defined in the @IndexingOptions annotation
var indices = jedis.ftList();
assertThat(indices).contains("MyCustomHashIndex");
}

@Test
void testFreeFormTextSearchOrderIssue() {
customIndexHashRepository.deleteAll();
CustomIndexHash redis1 = customIndexHashRepository.save(CustomIndexHash.of("Redis", "wwwabccom"));
CustomIndexHash redis2 = customIndexHashRepository.save(CustomIndexHash.of("Redis", "wwwxyznet"));
CustomIndexHash microsoft1 = customIndexHashRepository.save(CustomIndexHash.of("Microsoft", "wwwabcnet"));
CustomIndexHash microsoft2 = customIndexHashRepository.save(CustomIndexHash.of("Microsoft", "wwwxyzcom"));

var withFreeTextFirst = es.of(CustomIndexHash.class).filter("*co*").filter(CustomIndexHash$.FIRST.eq("Microsoft"))
.collect(Collectors.toList());

var withFreeTextLast = es.of(CustomIndexHash.class).filter(CustomIndexHash$.FIRST.eq("Microsoft")).filter("*co*")
.collect(Collectors.toList());

assertAll( //
() -> assertThat(withFreeTextLast).containsExactly(microsoft2),
() -> assertThat(withFreeTextFirst).containsExactly(microsoft2));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.redis.om.spring.fixtures.hash.model;

import com.redis.om.spring.annotations.IndexingOptions;
import com.redis.om.spring.annotations.Searchable;
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

@Data
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(force = true)
@IndexingOptions(indexName = "MyCustomHashIndex")
@RedisHash("custom_prefix")
public class CustomIndexHash {
@Id
private String id;

@NonNull
@Searchable(sortable = true)
private String first;

@NonNull
@Searchable(sortable = true)
private String second;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.redis.om.spring.fixtures.hash.repository;

import com.redis.om.spring.fixtures.hash.model.CustomIndexHash;
import com.redis.om.spring.repository.RedisDocumentRepository;

@SuppressWarnings("unused")
public interface CustomIndexHashRepository extends RedisDocumentRepository<CustomIndexHash, String> {
}

0 comments on commit bf11e3f

Please sign in to comment.