-
Notifications
You must be signed in to change notification settings - Fork 29
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
FMWK-199 Refactor implementation of paginated queries #658
Changes from 4 commits
ce93b21
53cfc40
6ff3802
5d34e37
52eb141
f6ad97c
6328dd2
2e80823
e9c4409
35595d0
160e517
1aaad1d
78adfb4
afa5f62
cf424a4
660af78
ccc0f25
ba5178f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -896,6 +896,8 @@ <T, S> List<?> findByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, Clas | |
*/ | ||
<T> Stream<T> findInRange(long offset, long limit, Sort sort, Class<T> targetClass, String setName); | ||
|
||
<T> Stream<T> findUsingQueryWithoutPostProcessing(Class<?> entityClass, Class<T> targetClass, Query query); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does entityClass is wrapped with |
||
|
||
/** | ||
* Check if a document exists by providing document id and entityClass (set name will be determined by the given | ||
* entityClass). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -814,7 +814,7 @@ public <T, S> Object findByIdUsingQuery(Object id, Class<T> entityClass, Class<S | |
Assert.notNull(entityClass, "Entity class must not be null!"); | ||
Assert.notNull(setName, "Set name must not be null!"); | ||
|
||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getCriteria().getCriteriaObject() : null; | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getQualifier() : null; | ||
try { | ||
AerospikePersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(entityClass); | ||
Key key = getKey(id, setName); | ||
|
@@ -944,6 +944,12 @@ private <T> Stream<T> findUsingQueryWithPostProcessing(String setName, Class<T> | |
return applyPostProcessingOnResults(results, query); | ||
} | ||
|
||
public <T> Stream<T> findUsingQueryWithoutPostProcessing(Class<?> entityClass, Class<T> targetClass, Query query) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add |
||
verifyUnsortedWithOffset(query.getSort(), query.getOffset()); | ||
return findUsingQueryWithDistinctPredicate(getSetName(entityClass), targetClass, | ||
getDistinctPredicate(query), query); | ||
} | ||
|
||
private <T> Stream<T> findUsingQueryWithDistinctPredicate(String setName, Class<T> targetClass, | ||
Predicate<KeyRecord> distinctPredicate, | ||
Query query) { | ||
|
@@ -1273,7 +1279,7 @@ private <T> Stream<T> applyPostProcessingOnResults(Stream<T> results, Sort sort, | |
} | ||
|
||
private <T> Stream<KeyRecord> findRecordsUsingQuery(String setName, Class<T> targetClass, Query query) { | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getCriteria().getCriteriaObject() : null; | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getQualifier() : null; | ||
if (qualifier != null) { | ||
Qualifier idQualifier = getOneIdQualifier(qualifier); | ||
if (idQualifier != null) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -868,6 +868,8 @@ <T, S> Flux<?> findByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, Clas | |
*/ | ||
<T, S> Flux<S> findInRange(long offset, long limit, Sort sort, Class<T> entityClass, Class<S> targetClass); | ||
|
||
<T> Flux<T> findUsingQueryWithoutPostProcessing(Class<?> entityClass, Class<T> targetClass, Query query); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Javadoc is required There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
|
||
/** | ||
* Reactively check if document exists by providing document id and entityClass (set name will be determined by the | ||
* given entityClass). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1177,6 +1177,12 @@ private <T> Flux<T> findUsingQueryWithPostProcessing(String setName, Class<T> ta | |
return results; | ||
} | ||
|
||
public <T> Flux<T> findUsingQueryWithoutPostProcessing(Class<?> entityClass, Class<T> targetClass, Query query) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add |
||
verifyUnsortedWithOffset(query.getSort(), query.getOffset()); | ||
return findUsingQueryWithDistinctPredicate(getSetName(entityClass), targetClass, | ||
getDistinctPredicate(query), query); | ||
} | ||
|
||
private void verifyUnsortedWithOffset(Sort sort, long offset) { | ||
if ((sort == null || sort.isUnsorted()) | ||
&& offset > 0) { | ||
|
@@ -1229,7 +1235,7 @@ private <T> Flux<T> findUsingQueryWithDistinctPredicate(String setName, Class<T> | |
} | ||
|
||
private <T> Flux<KeyRecord> findRecordsUsingQuery(String setName, Class<T> targetClass, Query query) { | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getCriteria().getCriteriaObject() : null; | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getQualifier() : null; | ||
if (qualifier != null) { | ||
Qualifier idQualifier = getOneIdQualifier(qualifier); | ||
if (idQualifier != null) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,6 +54,7 @@ public class QueryEngine { | |
* scans, set this property to true. | ||
*/ | ||
private boolean scansEnabled = false; | ||
private int queryMaxRecords = 100000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be taken from |
||
|
||
public QueryEngine(IAerospikeClient client, StatementBuilder statementBuilder, | ||
FilterExpressionsBuilder filterExpressionsBuilder, QueryPolicy queryPolicy) { | ||
|
@@ -85,7 +86,7 @@ public KeyRecordIterator select(String namespace, String set, @Nullable Query qu | |
* @return A KeyRecordIterator to iterate over the results | ||
*/ | ||
public KeyRecordIterator select(String namespace, String set, String[] binNames, @Nullable Query query) { | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getCriteria().getCriteriaObject() : null; | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getQualifier() : null; | ||
/* | ||
* singleton using primary key | ||
*/ | ||
|
@@ -105,6 +106,7 @@ public KeyRecordIterator select(String namespace, String set, String[] binNames, | |
* query with filters | ||
*/ | ||
Statement statement = statementBuilder.build(namespace, set, query, binNames); | ||
statement.setMaxRecords(queryMaxRecords); | ||
QueryPolicy localQueryPolicy = new QueryPolicy(queryPolicy); | ||
localQueryPolicy.filterExp = filterExpressionsBuilder.build(query); | ||
|
||
|
@@ -128,6 +130,11 @@ public void setScansEnabled(boolean scansEnabled) { | |
this.scansEnabled = scansEnabled; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
public void setQueryMaxRecords(int queryMaxRecords) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
this.queryMaxRecords = queryMaxRecords; | ||
} | ||
|
||
@Deprecated(since = "4.6.0", forRemoval = true) | ||
public enum Meta { | ||
KEY, | ||
TTL, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,7 @@ public class ReactorQueryEngine { | |
* scans, set this property to true. | ||
*/ | ||
private boolean scansEnabled = false; | ||
private int queryMaxRecords = 100000; | ||
|
||
public ReactorQueryEngine(IAerospikeReactorClient client, StatementBuilder statementBuilder, | ||
FilterExpressionsBuilder filterExpressionsBuilder, QueryPolicy queryPolicy) { | ||
|
@@ -81,7 +82,7 @@ public Flux<KeyRecord> select(String namespace, String set, @Nullable Query quer | |
* @return A Flux<KeyRecord> to iterate over the results | ||
*/ | ||
public Flux<KeyRecord> select(String namespace, String set, String[] binNames, @Nullable Query query) { | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getCriteria().getCriteriaObject() : null; | ||
Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getQualifier() : null; | ||
/* | ||
* singleton using primary key | ||
*/ | ||
|
@@ -96,6 +97,7 @@ public Flux<KeyRecord> select(String namespace, String set, String[] binNames, @ | |
* query with filters | ||
*/ | ||
Statement statement = statementBuilder.build(namespace, set, query, binNames); | ||
statement.setMaxRecords(queryMaxRecords); | ||
QueryPolicy localQueryPolicy = new QueryPolicy(queryPolicy); | ||
localQueryPolicy.filterExp = filterExpressionsBuilder.build(query); | ||
if (!scansEnabled && statement.getFilter() == null) { | ||
|
@@ -115,4 +117,8 @@ private Mono<KeyRecord> getRecord(Policy policy, Key key, String[] binNames) { | |
public void setScansEnabled(boolean scansEnabled) { | ||
this.scansEnabled = scansEnabled; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
public void setQueryMaxRecords(int queryMaxRecords) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
this.queryMaxRecords = queryMaxRecords; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,6 @@ | |
*/ | ||
package org.springframework.data.aerospike.repository.query; | ||
|
||
import org.springframework.data.aerospike.core.AerospikeOperations; | ||
import org.springframework.data.aerospike.core.AerospikeTemplate; | ||
import org.springframework.data.aerospike.query.Qualifier; | ||
import org.springframework.data.domain.PageImpl; | ||
|
@@ -40,15 +39,15 @@ | |
*/ | ||
public class AerospikePartTreeQuery extends BaseAerospikePartTreeQuery { | ||
|
||
private final AerospikeOperations operations; | ||
private final AerospikeTemplate template; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why template instead of operations? |
||
|
||
public AerospikePartTreeQuery(QueryMethod queryMethod, | ||
QueryMethodEvaluationContextProvider evalContextProvider, | ||
AerospikeTemplate aerospikeTemplate, | ||
Class<? extends AbstractQueryCreator<?, ?>> queryCreator) { | ||
super(queryMethod, evalContextProvider, queryCreator); | ||
|
||
this.operations = aerospikeTemplate; | ||
this.template = aerospikeTemplate; | ||
} | ||
|
||
@Override | ||
|
@@ -60,32 +59,36 @@ public Object execute(Object[] parameters) { | |
|
||
// queries that include id have their own processing flow | ||
if (parameters != null && parameters.length > 0) { | ||
Qualifier criteria = query.getCriteria().getCriteriaObject(); | ||
Qualifier criteria = query.getQualifier(); | ||
List<Object> ids; | ||
if (criteria.hasSingleId()) { | ||
ids = getIdValue(criteria); | ||
return operations.findByIdsUsingQuery(ids, entityClass, targetClass, null); | ||
return template.findByIdsUsingQuery(ids, entityClass, targetClass, null); | ||
} else { | ||
Qualifier idQualifier; | ||
if ((idQualifier = getIdQualifier(criteria)) != null) { | ||
ids = getIdValue(idQualifier); | ||
return operations.findByIdsUsingQuery(ids, entityClass, targetClass, | ||
return template.findByIdsUsingQuery(ids, entityClass, targetClass, | ||
new Query(excludeIdQualifier(criteria))); | ||
} | ||
} | ||
} | ||
|
||
if (queryMethod.isPageQuery() || queryMethod.isSliceQuery()) { | ||
Stream<?> result = findByQuery(query, targetClass); | ||
List<?> results = result.toList(); | ||
Pageable pageable = accessor.getPageable(); | ||
long numberOfAllResults = operations.count(query, entityClass); | ||
Stream<?> unprocessedResultsStream = | ||
template.findUsingQueryWithoutPostProcessing(entityClass, targetClass, query); | ||
// Assuming there is enough memory | ||
// and configuration parameter AerospikeDataSettings.queryMaxRecords is less than Integer.MAX_VALUE | ||
List<?> unprocessedResults = unprocessedResultsStream.toList(); | ||
long numberOfAllResults = unprocessedResults.size(); | ||
List<?> resultsPaginated = applyPostProcessingOnResults(unprocessedResults.stream(), query).toList(); | ||
|
||
Pageable pageable = accessor.getPageable(); | ||
if (queryMethod.isSliceQuery()) { | ||
boolean hasNext = numberOfAllResults > pageable.getPageSize() * (pageable.getOffset() + 1); | ||
return new SliceImpl(results, pageable, hasNext); | ||
return new SliceImpl(resultsPaginated, pageable, hasNext); | ||
} else { | ||
return new PageImpl(results, pageable, numberOfAllResults); | ||
return new PageImpl(resultsPaginated, pageable, numberOfAllResults); | ||
} | ||
} else if (queryMethod.isStreamQuery()) { | ||
return findByQuery(query, targetClass); | ||
|
@@ -102,9 +105,9 @@ public Object execute(Object[] parameters) { | |
private Stream<?> findByQuery(Query query, Class<?> targetClass) { | ||
// Run query and map to different target class. | ||
if (targetClass != null && targetClass != entityClass) { | ||
return operations.find(query, entityClass, targetClass); | ||
return template.find(query, entityClass, targetClass); | ||
} | ||
// Run query and map to entity class type. | ||
return operations.find(query, entityClass); | ||
return template.find(query, entityClass); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Javadoc is required