Skip to content

Commit

Permalink
FMWK-524 Support other Spring Data keywords (#774)
Browse files Browse the repository at this point in the history
  • Loading branch information
agrgr authored Sep 10, 2024
1 parent d7fef31 commit f3e7d0c
Show file tree
Hide file tree
Showing 28 changed files with 1,723 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,45 @@ public interface AerospikeOperations {
*/
<T> boolean delete(T document, String setName);

/**
* Delete records using a query using the set associated with the given entityClass.
*
* @param query The query to check if any matching records exist. Must not be {@literal null}.
* @param entityClass The class to extract set name from. Must not be {@literal null}.
*/
<T> void delete(Query query, Class<T> entityClass);

/**
* Delete records using a query within the given set.
*
* @param query The query to check if any matching records exist. Must not be {@literal null}.
* @param entityClass The class to translate to returned records into. Must not be {@literal null}.
* @param setName Set name to use. Must not be {@literal null}.
*/
<T> void delete(Query query, Class<T> entityClass, String setName);

/**
* Count existing records by ids and a query using the given entityClass.
* <p>
* The records will be mapped to the given entityClass.
*
* @param ids The ids of the documents to find. Must not be {@literal null}.
* @param entityClass The class to extract set name from. Must not be {@literal null}.
* @param query The {@link Query} to filter results. Optional argument (null if no filtering required).
*/
<T> void deleteByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, @Nullable Query query);

/**
* Count existing records by ids and a query using the given entityClass within the set.
* <p>
* The records will be mapped to the given entityClass.
*
* @param ids The ids of the documents to find. Must not be {@literal null}.
* @param entityClass The class to extract set name from. Must not be {@literal null}.
* @param setName Set name to use. Must not be {@literal null}.
* @param query The {@link Query} to filter results. Optional argument (null if no filtering required).
*/
<T> void deleteByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, String setName, @Nullable Query query);

/**
* Delete multiple records in one batch request. The policies are analogous to {@link #delete(Object)}.
Expand Down Expand Up @@ -1026,17 +1065,40 @@ <T, S> List<?> findByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, Clas
* @param entityClass The class to extract set name from. Must not be {@literal null}.
* @return whether any matching records exist.
*/
<T> boolean existsByQuery(Query query, Class<T> entityClass);
<T> boolean exists(Query query, Class<T> entityClass);

/**
* Check using a query if any matching records exist within the given set.
*
* @param query The query to check if any matching records exist. Must not be {@literal null}.
* @param entityClass The class to translate to returned records into. Must not be {@literal null}.
* @param setName Set name to use. Must not be {@literal null}.
* @param query The query to check if any matching records exist. Must not be {@literal null}.
* @param setName Set name to use. Must not be {@literal null}.
* @return whether any matching records exist.
*/
<T> boolean existsByQuery(Query query, Class<T> entityClass, String setName);
boolean exists(Query query, String setName);

/**
* Find if there are existing records by ids and a query using the given entityClass.
* <p>
* The records will not be mapped to the given entityClass. The results are not processed (no pagination).
*
* @param ids The ids of the documents to find. Must not be {@literal null}.
* @param entityClass The class to extract set name from. Must not be {@literal null}.
* @param query The {@link Query} to filter results. Optional argument (null if no filtering required).
* @return True if matching records exist, otherwise false.
*/
<T> boolean existsByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, @Nullable Query query);

/**
* Find if there are existing records by ids and a query using the given entityClass within the set.
* <p>
* The records will not be mapped to a Java class. The results are not processed (no pagination).
*
* @param ids The ids of the documents to find. Must not be {@literal null}.
* @param setName Set name to use. Must not be {@literal null}.
* @param query The {@link Query} to filter results. Optional argument (null if no filtering required).
* @return True if matching records exist, otherwise false.
*/
boolean existsByIdsUsingQuery(Collection<?> ids, String setName, @Nullable Query query);

/**
* Return the amount of records in the set determined by the given entityClass.
Expand Down Expand Up @@ -1072,6 +1134,30 @@ <T, S> List<?> findByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, Clas
*/
long count(Query query, String setName);

/**
* Count existing records by ids and a query using the given entityClass.
* <p>
* The records will not be mapped to the given entityClass. The results are not processed (no pagination).
*
* @param ids The ids of the documents to find. Must not be {@literal null}.
* @param entityClass The class to extract set name from. Must not be {@literal null}.
* @param query The {@link Query} to filter results. Optional argument (null if no filtering required).
* @return quantity of matching records.
*/
<T> long countByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, @Nullable Query query);

/**
* Count existing records by ids and a query using the given entityClass within the set.
* <p>
* The records will not be mapped to a Java class. The results are not processed (no pagination).
*
* @param ids The ids of the documents to find. Must not be {@literal null}.
* @param setName Set name to use. Must not be {@literal null}.
* @param query The {@link Query} to filter results. Optional argument (null if no filtering required).
* @return quantity of matching records.
*/
long countByIdsUsingQuery(Collection<?> ids, String setName, @Nullable Query query);

/**
* Execute query, apply statement's aggregation function, and return result iterator.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.springframework.data.aerospike.util.Utils;
import org.springframework.data.domain.Sort;
import org.springframework.data.util.StreamUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.time.Instant;
Expand All @@ -59,6 +60,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -452,6 +454,52 @@ public boolean deleteById(Object id, String setName) {
}
}

public <T> void delete(Query query, Class<T> entityClass, String setName) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(entityClass, "Entity class must not be null!");
Assert.notNull(setName, "Set name must not be null!");

List<T> findQueryResults = find(query, entityClass, setName).filter(Objects::nonNull).toList();

if (!findQueryResults.isEmpty()) {
if (serverVersionSupport.isBatchWriteSupported()) {
deleteAll(findQueryResults);
} else {
findQueryResults.forEach(this::delete);
}
}
}

@Override
public <T> void delete(Query query, Class<T> entityClass) {
Assert.notNull(query, "Query passed in to exist can't be null");
Assert.notNull(entityClass, "Class must not be null!");

delete(query, entityClass, getSetName(entityClass));
}

@Override
public <T> void deleteByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, @Nullable Query query) {
deleteByIdsUsingQuery(ids, entityClass, getSetName(entityClass), query);
}

@Override
public <T> void deleteByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, String setName,
@Nullable Query query) {
List<Object> findQueryResults = findByIdsUsingQuery(ids, entityClass, entityClass, setName, query)
.stream()
.filter(Objects::nonNull)
.collect(Collectors.toUnmodifiableList());

if (!findQueryResults.isEmpty()) {
if (serverVersionSupport.isBatchWriteSupported()) {
deleteAll(findQueryResults);
} else {
findQueryResults.forEach(this::delete);
}
}
}

@Override
public <T> void deleteAll(Iterable<T> documents) {
String setName = getSetName(documents.iterator().next());
Expand Down Expand Up @@ -981,10 +1029,36 @@ public <T, S> List<?> findByIdsUsingQuery(Collection<?> ids, Class<T> entityClas
target = entityClass;
}

return IntStream.range(0, keys.length)
Stream<?> results = IntStream.range(0, keys.length)
.filter(index -> aeroRecords[index] != null)
.mapToObj(index -> mapToEntity(keys[index], target, aeroRecords[index]))
.collect(Collectors.toList());
.mapToObj(index -> mapToEntity(keys[index], target, aeroRecords[index]));

return applyPostProcessingOnResults(results, query).collect(Collectors.toList());
} catch (AerospikeException e) {
throw translateError(e);
}
}

public IntStream findByIdsUsingQueryWithoutMapping(Collection<?> ids, String setName, Query query) {
Assert.notNull(setName, "Set name must not be null!");

try {
Key[] keys;
if (ids == null || ids.isEmpty()) {
keys = new Key[0];
} else {
keys = ids.stream()
.map(id -> getKey(id, setName))
.toArray(Key[]::new);
}

BatchPolicy policy = getBatchPolicyFilterExp(query);

Record[] aeroRecords;
aeroRecords = getAerospikeClient().get(policy, keys);

return IntStream.range(0, keys.length)
.filter(index -> aeroRecords[index] != null);
} catch (AerospikeException e) {
throw translateError(e);
}
Expand Down Expand Up @@ -1122,19 +1196,31 @@ public boolean exists(Object id, String setName) {
}

@Override
public <T> boolean existsByQuery(Query query, Class<T> entityClass) {
public <T> boolean exists(Query query, Class<T> entityClass) {
Assert.notNull(query, "Query passed in to exist can't be null");
Assert.notNull(entityClass, "Class must not be null!");
return existsByQuery(query, entityClass, getSetName(entityClass));
return exists(query, getSetName(entityClass));
}

@Override
public <T> boolean existsByQuery(Query query, Class<T> entityClass, String setName) {
public boolean exists(Query query, String setName) {
Assert.notNull(query, "Query passed in to exist can't be null");
Assert.notNull(entityClass, "Class must not be null!");
Assert.notNull(setName, "Set name must not be null!");

return find(query, entityClass, setName).findAny().isPresent();
return findKeyRecordsUsingQuery(setName, query).findAny().isPresent();
}

@Override
public <T> boolean existsByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, @Nullable Query query) {
return existsByIdsUsingQuery(ids, getSetName(entityClass), query);
}

@Override
public boolean existsByIdsUsingQuery(Collection<?> ids, String setName, @Nullable Query query) {
long findQueryResults = findByIdsUsingQueryWithoutMapping(ids, setName, query)
.filter(Objects::nonNull)
.count();
return findQueryResults > 0;
}

@Override
Expand Down Expand Up @@ -1169,11 +1255,10 @@ public <T> long count(Query query, Class<T> entityClass) {

@Override
public long count(Query query, String setName) {
Stream<KeyRecord> results = countRecordsUsingQuery(setName, query);
return results.count();
return findKeyRecordsUsingQuery(setName, query).count();
}

private Stream<KeyRecord> countRecordsUsingQuery(String setName, Query query) {
private Stream<KeyRecord> findKeyRecordsUsingQuery(String setName, Query query) {
Assert.notNull(setName, "Set name must not be null!");

Qualifier qualifier = queryCriteriaIsNotNull(query) ? query.getCriteriaObject() : null;
Expand All @@ -1198,6 +1283,18 @@ private Stream<KeyRecord> countRecordsUsingQuery(String setName, Query query) {
});
}

@Override
public <T> long countByIdsUsingQuery(Collection<?> ids, Class<T> entityClass, @Nullable Query query) {
return countByIdsUsingQuery(ids, getSetName(entityClass), query);
}

@Override
public long countByIdsUsingQuery(Collection<?> ids, String setName, @Nullable Query query) {
return findByIdsUsingQueryWithoutMapping(ids, setName, query)
.filter(Objects::nonNull)
.count();
}

@Override
public <T> ResultSet aggregate(Filter filter, Class<T> entityClass,
String module, String function, List<Value> arguments) {
Expand Down Expand Up @@ -1387,15 +1484,17 @@ private <T> Stream<T> findWithPostProcessing(String setName, Class<T> targetClas
}

private <T> Stream<T> applyPostProcessingOnResults(Stream<T> results, Query query) {
if (query.getSort() != null && query.getSort().isSorted()) {
Comparator<T> comparator = getComparator(query);
results = results.sorted(comparator);
}
if (query.hasOffset()) {
results = results.skip(query.getOffset());
}
if (query.hasRows()) {
results = results.limit(query.getRows());
if (query != null) {
if (query.getSort() != null && query.getSort().isSorted()) {
Comparator<T> comparator = getComparator(query);
results = results.sorted(comparator);
}
if (query.hasOffset()) {
results = results.skip(query.getOffset());
}
if (query.hasRows()) {
results = results.limit(query.getRows());
}
}

return results;
Expand Down
Loading

0 comments on commit f3e7d0c

Please sign in to comment.