Skip to content

Commit

Permalink
Support interface based projections
Browse files Browse the repository at this point in the history
  • Loading branch information
maorohana-redis committed May 3, 2024
1 parent 523676f commit efec4c3
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@
import org.springframework.data.keyvalue.core.KeyValueOperations;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.*;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.PartTree;
Expand All @@ -49,9 +46,6 @@
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static com.redis.om.spring.util.ObjectUtils.getIdFieldForEntityClass;
import static com.redis.om.spring.util.ObjectUtils.getValueForField;

public class RediSearchQuery implements RepositoryQuery {

private static final Log logger = LogFactory.getLog(RediSearchQuery.class);
Expand Down Expand Up @@ -378,6 +372,12 @@ else if (fieldType == Point.class) {

@Override
public Object execute(Object[] parameters) {
ParameterAccessor accessor = new ParametersParameterAccessor(this.getQueryMethod().getParameters(), parameters);
ResultProcessor processor = this.queryMethod.getResultProcessor().withDynamicProjection(accessor);
return processor.processResult(this.doExecute(parameters));
}

public Object doExecute(Object[] parameters) {
Optional<String> maybeBloomFilter = bloomQueryExecutor.getBloomFilter();
Optional<String> maybeCuckooFilter = cuckooQueryExecutor.getCuckooFilter();

Expand Down Expand Up @@ -477,32 +477,37 @@ private Object executeQuery(Object[] parameters) {
} else if (queryMethod.isPageQuery()) {
Gson gson = getGson();
List<Object> content = searchResult.getDocuments().stream()
.map(d -> gson.fromJson(SafeEncoder.encode((byte[])d.get("$")), queryMethod.getReturnedObjectType()))
.map(d -> gson.fromJson(SafeEncoder.encode((byte[])d.get("$")), domainType))
.collect(Collectors.toList());

if (maybePageable.isPresent()) {
Pageable pageable = maybePageable.get();
result = new PageImpl<>(content, pageable, searchResult.getTotalResults());
}

} else if (queryMethod.isQueryForEntity() && !queryMethod.isCollectionQuery()) {
} else if (!queryMethod.isCollectionQuery()) {
// handle the case where we have a single entity result and we the query results are empty
if (!searchResult.getDocuments().isEmpty()) {
Gson gson = getGson();
Document doc = searchResult.getDocuments().get(0);
Object json = doc != null ? SafeEncoder.encode((byte[])doc.get("$")) : "";
result = gson.fromJson(json.toString(), queryMethod.getReturnedObjectType());
result = gson.fromJson(json.toString(), domainType);
}
} else if ((queryMethod.isQueryForEntity() && queryMethod.isCollectionQuery()) || this.type == RediSearchQueryType.DELETE) {
} else if ((queryMethod.isCollectionQuery()) || this.type == RediSearchQueryType.DELETE) {
Gson gson = getGson();
result = searchResult.getDocuments().stream()
.map(d -> gson.fromJson(SafeEncoder.encode((byte[])d.get("$")), queryMethod.getReturnedObjectType()))
.map(d -> gson.fromJson(SafeEncoder.encode((byte[])d.get("$")), domainType))
.collect(Collectors.toList());
}

return result;
}

static class Company {
public String url;
public String name;
}

private Object executeDeleteQuery(Object[] parameters) {
SearchOperations<String> ops = modulesOperations.opsForSearch(searchIndex);
String baseQuery = prepareQuery(parameters, true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.redis.om.spring.repository;

public interface DocumentProjection {
String getName();
RecursiveSummary getRecursiveProjection();

interface RecursiveSummary {
String getRecursiveProp1();
}

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

import com.redis.om.spring.annotations.Document;
import lombok.Data;
import org.springframework.data.annotation.Id;

import java.util.UUID;

@Document
@Data
public class DocumentProjectionPojo {

@Id
private String id;

private String name;

private RecursiveProjection recursiveProjection;

public DocumentProjectionPojo() {
this.id = UUID.randomUUID().toString();
}


@Data
static class RecursiveProjection {
private String recursiveProp1;
private String recursiveProp2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.redis.om.spring.repository;

import java.util.Collection;
import java.util.Optional;

public interface DocumentProjectionRepository extends RedisDocumentRepository<DocumentProjectionPojo, String> {
Optional<DocumentProjection> findByName(String name);
Collection<DocumentProjection> findAllByName(String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.redis.om.spring.repository;

import com.redis.om.spring.AbstractBaseDocumentTest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;

class DocumentProjectionTest extends AbstractBaseDocumentTest {

public static final String TEST_NAME = "testName";
public static final String TEST_REC_1 = "test1";
public static final String TEST_REC_2 = "test2";
private final DocumentProjectionRepository documentProjectionRepository;

@Autowired
DocumentProjectionTest(DocumentProjectionRepository documentProjectionRepository) {
this.documentProjectionRepository = documentProjectionRepository;
}

@BeforeEach
void setUp() {
for (int i = 0; i < 2; i++) {
DocumentProjectionPojo entity = new DocumentProjectionPojo();
entity.setName(TEST_NAME);
DocumentProjectionPojo.RecursiveProjection recursiveProjection = new DocumentProjectionPojo.RecursiveProjection();
recursiveProjection.setRecursiveProp1(TEST_REC_1);
recursiveProjection.setRecursiveProp2(TEST_REC_2);
entity.setRecursiveProjection(recursiveProjection);
documentProjectionRepository.save(entity);
}
}

@Test
void testEntityProjection() {
Optional<DocumentProjection> byNameProjection = documentProjectionRepository.findByName(TEST_NAME);
assertTrue(byNameProjection.isPresent());
assertEquals(TEST_NAME, byNameProjection.get().getName());
assertNotNull(byNameProjection.get().getRecursiveProjection());
assertEquals(TEST_REC_1, byNameProjection.get().getRecursiveProjection().getRecursiveProp1());
}

@Test
void testCollectionProjection() {
Collection<DocumentProjection> byNameProjection = documentProjectionRepository.findAllByName(TEST_NAME);
assertNotNull(byNameProjection);
assertEquals(2, byNameProjection.size());
byNameProjection.forEach(documentProjection -> {
assertNotNull(documentProjection.getName());
assertNotNull(documentProjection.getRecursiveProjection());
});
}

@AfterEach
void tearDown() {
documentProjectionRepository.deleteAll();
}

}

0 comments on commit efec4c3

Please sign in to comment.