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

feature: handle search aliased fields with special characters (resolv… #435

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.github.f4b6a3.ulid.Ulid;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.redis.om.spring.annotations.*;
import com.redis.om.spring.ops.RedisModulesOperations;
import com.redis.om.spring.ops.search.SearchOperations;
Expand Down Expand Up @@ -217,8 +218,8 @@ private List<SchemaField> findIndexFields(java.lang.reflect.Field field, String
// Also UUID and Ulid (classes whose toString() is a valid text representation
// of the value)
//
if (CharSequence.class.isAssignableFrom(
fieldType) || (fieldType == Boolean.class) || (fieldType == UUID.class) || (fieldType == Ulid.class)) {
if (CharSequence.class.isAssignableFrom(fieldType) || //
(fieldType == Boolean.class) || (fieldType == UUID.class) || (fieldType == Ulid.class)) {
fields.add(indexAsTagFieldFor(field, isDocument, prefix, indexed.sortable(), indexed.separator(),
indexed.arrayIndex(), indexed.alias()));
} else if (fieldType.isEnum()) {
Expand Down Expand Up @@ -454,13 +455,15 @@ private VectorField indexAsVectorFieldFor(java.lang.reflect.Field field, boolean

private SchemaField indexAsTagFieldFor(java.lang.reflect.Field field, boolean isDocument, String prefix,
boolean sortable, String separator, int arrayIndex, String annotationAlias) {
SerializedName serializedName = field.getAnnotation(SerializedName.class);
String fname = (serializedName != null) ? serializedName.value() : field.getName();
TypeInformation<?> typeInfo = TypeInformation.of(field.getType());
String fieldPrefix = getFieldPrefix(prefix, isDocument);
String index = (arrayIndex != Integer.MIN_VALUE) ? ".[" + arrayIndex + "]" : "[*]";
String fieldPostfix = (isDocument && typeInfo.isCollectionLike() && !field.isAnnotationPresent(JsonAdapter.class)) ?
index :
"";
String name = fieldPrefix + field.getName() + fieldPostfix;
String name = fieldPrefix + fname + fieldPostfix;
String alias = (annotationAlias == null || annotationAlias.isBlank()) ?
QueryUtils.searchIndexFieldAliasFor(field, prefix) :
annotationAlias;
Expand Down Expand Up @@ -536,8 +539,10 @@ private List<SchemaField> indexAsNestedFieldFor(java.lang.reflect.Field field, S
}

private FieldName getFieldName(java.lang.reflect.Field field, boolean isDocument, String prefix, String alias) {
SerializedName serializedName = field.getAnnotation(SerializedName.class);
String fname = (serializedName != null) ? serializedName.value() : field.getName();
String fieldPrefix = getFieldPrefix(prefix, isDocument);
String name = fieldPrefix + field.getName();
String name = fieldPrefix + fname;
FieldName fieldName = FieldName.of(name);
fieldName = fieldName.as(alias);
return fieldName;
Expand Down Expand Up @@ -758,9 +763,11 @@ private Optional<SchemaField> createIndexedFieldForIdField(Class<?> cl, List<Sch
private Optional<SchemaField> createIndexedFieldForReferenceIdField( //
java.lang.reflect.Field referenceIdField, //
boolean isDocument) {
SerializedName serializedName = referenceIdField.getAnnotation(SerializedName.class);
String fname = (serializedName != null) ? serializedName.value() : referenceIdField.getName();

String fieldPrefix = getFieldPrefix("", isDocument);
FieldName fieldName = FieldName.of(fieldPrefix + referenceIdField.getName());
FieldName fieldName = FieldName.of(fieldPrefix + fname);
fieldName = fieldName.as(QueryUtils.searchIndexFieldAliasFor(referenceIdField, ""));
return Optional.of(
isDocument ? TagField.of(fieldName).separator('|') : TagField.of(fieldName).separator('|').sortable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ private String prepareQuery(final Object[] parameters, boolean excludeNullParams
if (excludeNullParams && (fieldClauses.getSecond() == QueryClause.IS_NULL || fieldClauses.getSecond() == QueryClause.IS_NOT_NULL)) {
return "";
}
String fieldName = fieldClauses.getFirst();
String fieldName = QueryUtils.escape(fieldClauses.getFirst());
QueryClause queryClause = fieldClauses.getSecond();
int paramsCnt = queryClause.getClauseTemplate().getNumberOfArguments();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ private String prepareQuery(final Object[] parameters, boolean excludeNullParams
if (excludeNullParams && (fieldClauses.getSecond() == QueryClause.IS_NULL || fieldClauses.getSecond() == QueryClause.IS_NOT_NULL)) {
return "";
}
String fieldName = fieldClauses.getFirst();
String fieldName = QueryUtils.escape(fieldClauses.getFirst());
QueryClause queryClause = fieldClauses.getSecond();
int paramsCnt = queryClause.getClauseTemplate().getNumberOfArguments();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package com.redis.om.spring.annotations.document;

import com.redis.om.spring.AbstractBaseDocumentTest;
import com.redis.om.spring.annotations.document.fixtures.SKU;
import com.redis.om.spring.annotations.document.fixtures.SKUCacheRepository;
import com.redis.om.spring.annotations.document.fixtures.User2;
import com.redis.om.spring.annotations.document.fixtures.User2Repository;
import com.redis.om.spring.annotations.document.fixtures.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
Expand All @@ -24,6 +22,9 @@ class RepositoryIssuesTest extends AbstractBaseDocumentTest {
@Autowired
SKUCacheRepository skuCacheRepository;

@Autowired
StudentRepository studentRepository;

@BeforeEach
void cleanUp() {
repository.deleteAll();
Expand All @@ -37,6 +38,13 @@ void cleanUp() {
}
skuCacheRepository.saveAll(skuCaches);

studentRepository.deleteAll();
List<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
students.add(
Student.of((long) i, "Student" + i, LocalDateTime.now()));
}
studentRepository.saveAll(students);
}

// RediSearchQuery wrong preparedQuery #187
Expand Down Expand Up @@ -76,4 +84,14 @@ void testFindOneBy() {
() -> assertThat(result.getSkuNumber()).isEqualTo("A11111") //
);
}

@Test
void testFindByPropertyWithAliasWithHyphens() {
List<Student> result = studentRepository.findByUserName("Student2");

assertAll( //
() -> assertThat(result).hasSize(1),
() -> assertThat(result).extracting("userName").containsExactly("Student2") //
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.redis.om.spring.annotations.document.fixtures;

import com.google.gson.annotations.SerializedName;
import com.redis.om.spring.annotations.Document;
import com.redis.om.spring.annotations.Indexed;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.annotation.Id;

import java.time.LocalDateTime;

@Data
@Builder
@RequiredArgsConstructor(staticName = "of")
@Document
public class Student {

@Id
@NonNull
private Long id;

@Indexed(alias = "User-Name")// fieldName = "User-Name", schemaFieldType = SchemaFieldType.TAG
@SerializedName("User-Name")
@NonNull
private String userName;

@Indexed
@NonNull
private LocalDateTime eventTimestamp;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.redis.om.spring.annotations.document.fixtures;

import com.redis.om.spring.repository.RedisDocumentRepository;

import java.util.List;

public interface StudentRepository extends RedisDocumentRepository<Student, Long> {
List<Student> findByUserName(String userName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
Expand Down Expand Up @@ -51,6 +52,9 @@
@Autowired
HashWithEnumRepository hashWithEnumRepository;

@Autowired
StudentRepository studentRepository;

@BeforeEach
void createTestDataIfNeeded() {
flushSearchIndexFor(Company.class);
Expand Down Expand Up @@ -81,6 +85,14 @@ void createTestDataIfNeeded() {
michael.setFavoriteFoods(Set.of("Steak and Kidney Pie", "Sunday Roast", "Bangers and Mash"));

personRepo.saveAll(List.of(john, gray, terryg, eric, terryj, michael));

studentRepository.deleteAll();
List<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
students.add(
Student.of((long) i, "Student" + i, LocalDateTime.now()));
}
studentRepository.saveAll(students);
}

@Test
Expand Down Expand Up @@ -634,4 +646,14 @@ void testOrderByInMethodName() {
() -> assertThat(onlyVal3).containsExactly(doc3) //
);
}

@Test
void testFindByPropertyWithAliasWithHyphens() {
List<Student> result = studentRepository.findByUserName("Student2");

assertAll( //
() -> assertThat(result).hasSize(1),
() -> assertThat(result).extracting("userName").containsExactly("Student2") //
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.redis.om.spring.annotations.hash.fixtures;

import com.google.gson.annotations.SerializedName;
import com.redis.om.spring.annotations.Document;
import com.redis.om.spring.annotations.Indexed;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

import java.time.LocalDateTime;

@Data
@Builder
@RequiredArgsConstructor(staticName = "of")
@RedisHash
public class Student {

@Id
@NonNull
private Long id;

@Indexed(alias = "User-Name")// fieldName = "User-Name", schemaFieldType = SchemaFieldType.TAG
@NonNull
private String userName;

@Indexed
@NonNull
private LocalDateTime eventTimestamp;

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

import com.redis.om.spring.repository.RedisDocumentRepository;
import com.redis.om.spring.repository.RedisEnhancedRepository;

import java.util.List;

public interface StudentRepository extends RedisEnhancedRepository<Student, Long> {
List<Student> findByUserName(String userName);
}
Loading