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

FMWK-345 Custom metadata queries: update metadata mapping #737

Merged
merged 13 commits into from
May 7, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.springframework.data.aerospike.core.model.GroupedEntities;
import org.springframework.data.aerospike.core.model.GroupedKeys;
import org.springframework.data.aerospike.repository.query.Query;
import org.springframework.data.aerospike.server.version.ServerVersionSupport;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.lang.Nullable;
Expand Down Expand Up @@ -78,6 +79,11 @@ public interface AerospikeOperations {
*/
MappingAerospikeConverter getAerospikeConverter();

/**
* @return server version support in use.
*/
ServerVersionSupport getServerVersionSupport();

/**
* @return Aerospike client in use.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ public MappingAerospikeConverter getAerospikeConverter() {
return this.converter;
}

public ServerVersionSupport getServerVersionSupport() {
return this.serverVersionSupport;
}

public String getNamespace() {
return namespace;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.data.aerospike.query.qualifier.Qualifier;
import org.springframework.data.aerospike.query.qualifier.QualifierKey;
import org.springframework.data.aerospike.repository.query.CriteriaDefinition;
import org.springframework.data.aerospike.server.version.ServerVersionSupport;
import org.springframework.data.util.Pair;

import java.util.Arrays;
Expand Down Expand Up @@ -1318,22 +1319,22 @@ private static Collection<?> getValueAsCollectionOrFail(Map<QualifierKey, Object
*/
private static Optional<Exp> getMetadataExp(Map<QualifierKey, Object> qualifierMap) {
CriteriaDefinition.AerospikeMetadata metadataField = getMetadataField(qualifierMap);
String field = getBinName(qualifierMap);
String binName = getBinName(qualifierMap);

if (metadataField != null && (field == null || field.isEmpty())) {
if (metadataField != null && (binName == null || binName.isEmpty())) {
FilterOperation operation = getOperation(qualifierMap);
switch (operation) {
case EQ, NOTEQ, LT, LTEQ, GT, GTEQ -> {
BinaryOperator<Exp> operationFunction = mapOperation(operation);
return Optional.of(
operationFunction.apply(
mapMetadataExp(metadataField),
mapMetadataExp(metadataField, getServerVersionSupport(qualifierMap)),
Exp.val(getValueAsLongOrFail(getValueAsObject(qualifierMap)))
)
);
}
case BETWEEN -> {
Exp metadata = mapMetadataExp(metadataField);
Exp metadata = mapMetadataExp(metadataField, getServerVersionSupport(qualifierMap));
Exp value = Exp.val(getValue(qualifierMap).toLong());
Exp secondValue = Exp.val(getSecondValue(qualifierMap).toLong());
return Optional.of(Exp.and(Exp.ge(metadata, value), Exp.lt(metadata, secondValue)));
Expand All @@ -1359,14 +1360,15 @@ private static Long getValueAsLongOrFail(Object value) {
}
}

private static Exp mapMetadataExp(CriteriaDefinition.AerospikeMetadata metadataField) {
private static Exp mapMetadataExp(CriteriaDefinition.AerospikeMetadata metadataField,
ServerVersionSupport versionSupport) {
return switch (metadataField) {
case SINCE_UPDATE_TIME -> Exp.sinceUpdate();
case LAST_UPDATE_TIME -> Exp.lastUpdate();
case VOID_TIME -> Exp.voidTime();
case TTL -> Exp.ttl();
case RECORD_SIZE_ON_DISK -> Exp.deviceSize();
case RECORD_SIZE_IN_MEMORY -> Exp.memorySize();
case RECORD_SIZE_ON_DISK -> versionSupport.isServerVersionGtOrEq7() ? Exp.recordSize() : Exp.deviceSize();
case RECORD_SIZE_IN_MEMORY -> versionSupport.isServerVersionGtOrEq7() ? Exp.recordSize() : Exp.memorySize();
default -> throw new IllegalStateException("Cannot map metadata Expression to " + metadataField);
};
}
Expand Down Expand Up @@ -1719,6 +1721,10 @@ private static CTX[] getCtx(List<String> ctxList) {
return ctxList != null ? resolveCtxList(ctxList) : null;
}

protected static ServerVersionSupport getServerVersionSupport(Map<QualifierKey, Object> qualifierMap) {
return (ServerVersionSupport) qualifierMap.get(SERVER_VERSION_SUPPORT);
}

public abstract Exp filterExp(Map<QualifierKey, Object> qualifierMap);

public abstract Filter sIndexFilter(Map<QualifierKey, Object> qualifierMap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.aerospike.client.Value;
import com.aerospike.client.command.ParticleType;
import com.aerospike.client.exp.Exp;
import org.springframework.data.aerospike.server.version.ServerVersionSupport;

import java.util.List;

Expand Down Expand Up @@ -110,4 +111,12 @@ public QualifierBuilder setNestedType(int type) {
this.map.put(NESTED_TYPE, type);
return this;
}

/**
* Set server version support.
*/
public QualifierBuilder setServerVersionSupport(ServerVersionSupport serverVersionSupport) {
this.map.put(SERVER_VERSION_SUPPORT, serverVersionSupport);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ public enum QualifierKey {
QUALIFIERS,
OPERATION,
DIGEST_KEY,
HAS_SINDEX_FILTER
HAS_SINDEX_FILTER,
SERVER_VERSION_SUPPORT
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public AerospikePartTreeQuery(QueryMethod queryMethod,
AerospikeTemplate operations,
Class<? extends AbstractQueryCreator<?, ?>> queryCreator) {
super(queryMethod, evalContextProvider, queryCreator, (AerospikeMappingContext) operations.getMappingContext(),
operations.getAerospikeConverter());
operations.getAerospikeConverter(), operations.getServerVersionSupport());
this.operations = operations;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.springframework.data.aerospike.query.FilterOperation;
import org.springframework.data.aerospike.query.QueryParam;
import org.springframework.data.aerospike.query.qualifier.Qualifier;
import org.springframework.data.aerospike.server.version.ServerVersionSupport;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PropertyPath;
Expand Down Expand Up @@ -56,13 +57,15 @@ public class AerospikeQueryCreator extends AbstractQueryCreator<Query, CriteriaD
private static final Logger LOG = LoggerFactory.getLogger(AerospikeQueryCreator.class);
private final AerospikeMappingContext context;
private final MappingAerospikeConverter converter;
private final ServerVersionSupport versionSupport;
private final boolean isCombinedQuery;

public AerospikeQueryCreator(PartTree tree, ParameterAccessor parameters,
AerospikeMappingContext context, MappingAerospikeConverter converter) {
public AerospikeQueryCreator(PartTree tree, ParameterAccessor parameters, AerospikeMappingContext context,
MappingAerospikeConverter converter, ServerVersionSupport versionSupport) {
super(tree, parameters);
this.context = context;
this.converter = converter;
this.versionSupport = versionSupport;
this.isCombinedQuery = tree.getParts().toList().size() > 1;
}

Expand Down Expand Up @@ -132,35 +135,35 @@ private IAerospikeQueryCreator getQueryCreator(Part part, AerospikePersistentPro
if (part.getProperty().hasNext()) { // a POJO field
PropertyPath nestedProperty = getNestedPropertyPath(part.getProperty());
queryCreator = new CollectionQueryCreator(part, nestedProperty, property, fieldName, queryParameters,
filterOperation, converter, true);
filterOperation, converter, true, versionSupport);
} else {
queryCreator = new CollectionQueryCreator(part, part.getProperty(), property, fieldName,
queryParameters, filterOperation, converter, false);
queryParameters, filterOperation, converter, false, versionSupport);
}
} else if (property.isMap()) {
if (part.getProperty().hasNext()) { // a POJO field
queryCreator = new MapQueryCreator(part, property, fieldName, queryParameters, filterOperation,
converter, true);
converter, versionSupport, true);
} else {
queryCreator = new MapQueryCreator(part, property, fieldName, queryParameters, filterOperation,
converter, false);
converter, versionSupport, false);
}
} else {
if (part.getProperty().hasNext()) { // a POJO field (a simple property field or an inner POJO)
PropertyPath nestedProperty = getNestedPropertyPath(part.getProperty());
if (isPojo(nestedProperty.getType())) {
queryCreator = new PojoQueryCreator(part, nestedProperty, property, fieldName, queryParameters,
filterOperation, converter, true);
filterOperation, converter, true, versionSupport);
} else {
queryCreator = new SimplePropertyQueryCreator(part, nestedProperty, property, fieldName,
queryParameters, filterOperation, converter, true);
queryParameters, filterOperation, converter, true, versionSupport);
}
} else if (isPojo(part.getProperty().getType())) { // a first level POJO or a Map
queryCreator = new PojoQueryCreator(part, part.getProperty(), property, fieldName, queryParameters,
filterOperation, converter, false);
filterOperation, converter, false, versionSupport);
} else {
queryCreator = new SimplePropertyQueryCreator(part, part.getProperty(), property, fieldName,
queryParameters, filterOperation, converter, false);
queryParameters, filterOperation, converter, false, versionSupport);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.data.aerospike.query.qualifier.Qualifier;
import org.springframework.data.aerospike.query.qualifier.QualifierBuilder;
import org.springframework.data.aerospike.repository.query.CriteriaDefinition.AerospikeQueryCriterion;
import org.springframework.data.aerospike.server.version.ServerVersionSupport;
import org.springframework.data.aerospike.util.Utils;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.repository.query.parser.Part;
Expand All @@ -30,7 +31,7 @@
public class AerospikeQueryCreatorUtils {

protected static Qualifier setQualifier(QualifierBuilder qb, String fieldName, FilterOperation op, Part part,
List<String> dotPath) {
List<String> dotPath, ServerVersionSupport versionSupport) {
qb.setBinName(fieldName)
.setFilterOperation(op)
.setIgnoreCase(ignoreCaseToBoolean(part));
Expand All @@ -41,7 +42,7 @@ protected static Qualifier setQualifier(QualifierBuilder qb, String fieldName, F
qb.setCtxList(getCtxFromDotPathArray(dotPathArr));
}
}

qb.setServerVersionSupport(versionSupport);
return qb.build();
}

Expand Down Expand Up @@ -95,14 +96,14 @@ protected static Class<?> getCollectionElementsClass(PropertyPath property) {
return property.getTypeInformation().getComponentType().getType();
}

protected static Qualifier qualifierAndConcatenated(MappingAerospikeConverter converter, List<Object> params,
protected static Qualifier qualifierAndConcatenated(ServerVersionSupport versionSupport, List<Object> params,
QualifierBuilder qb,
Part part, String fieldName, FilterOperation op,
List<String> dotPath) {
return qualifierAndConcatenated(converter, params, qb, part, fieldName, op, dotPath, false);
return qualifierAndConcatenated(versionSupport, params, qb, part, fieldName, op, dotPath, false);
}

protected static Qualifier qualifierAndConcatenated(MappingAerospikeConverter converter, List<Object> params,
protected static Qualifier qualifierAndConcatenated(ServerVersionSupport versionSupport, List<Object> params,
QualifierBuilder qb,
Part part, String fieldName, FilterOperation op,
List<String> dotPath, boolean containingMapKeyValuePairs) {
Expand All @@ -111,13 +112,13 @@ protected static Qualifier qualifierAndConcatenated(MappingAerospikeConverter co
qualifiers = new Qualifier[params.size() / 2]; // keys/values qty must be even
for (int i = 0, j = 0; i < params.size(); i += 2, j++) {
setQbValuesForMapByKey(qb, params.get(i), params.get(i + 1));
qualifiers[j] = setQualifier(qb, fieldName, op, part, dotPath);
qualifiers[j] = setQualifier(qb, fieldName, op, part, dotPath, versionSupport);
}
}
qualifiers = new Qualifier[params.size()];
for (int i = 0; i < params.size(); i++) {
setQbValuesForMapByKey(qb, params.get(i), params.get(i));
qualifiers[i] = setQualifier(qb, fieldName, op, part, dotPath);
qualifiers[i] = setQualifier(qb, fieldName, op, part, dotPath, versionSupport);
}

return Qualifier.and(qualifiers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.springframework.data.aerospike.convert.MappingAerospikeConverter;
import org.springframework.data.aerospike.mapping.AerospikeMappingContext;
import org.springframework.data.aerospike.query.qualifier.Qualifier;
import org.springframework.data.aerospike.server.version.ServerVersionSupport;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
Expand Down Expand Up @@ -49,18 +50,20 @@ public abstract class BaseAerospikePartTreeQuery implements RepositoryQuery {
private final Class<? extends AbstractQueryCreator<?, ?>> queryCreator;
private final AerospikeMappingContext context;
private final MappingAerospikeConverter converter;
private final ServerVersionSupport versionSupport;

protected BaseAerospikePartTreeQuery(QueryMethod queryMethod,
QueryMethodEvaluationContextProvider evalContextProvider,
Class<? extends AbstractQueryCreator<?, ?>> queryCreator,
AerospikeMappingContext context,
MappingAerospikeConverter converter) {
MappingAerospikeConverter converter, ServerVersionSupport versionSupport) {
this.queryMethod = queryMethod;
this.evaluationContextProvider = evalContextProvider;
this.queryCreator = queryCreator;
this.entityClass = queryMethod.getEntityInformation().getJavaType();
this.context = context;
this.converter = converter;
this.versionSupport = versionSupport;
}

@Override
Expand Down Expand Up @@ -120,8 +123,8 @@ Class<?> getTargetClass(ParametersParameterAccessor accessor) {
public Query createQuery(ParametersParameterAccessor accessor, PartTree tree) {
Constructor<? extends AbstractQueryCreator<?, ?>> constructor = ClassUtils
.getConstructorIfAvailable(queryCreator, PartTree.class, ParameterAccessor.class,
AerospikeMappingContext.class, MappingAerospikeConverter.class);
return (Query) BeanUtils.instantiateClass(constructor, tree, accessor, context, converter)
AerospikeMappingContext.class, MappingAerospikeConverter.class, ServerVersionSupport.class);
return (Query) BeanUtils.instantiateClass(constructor, tree, accessor, context, converter, versionSupport)
.createQuery();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.data.aerospike.query.FilterOperation;
import org.springframework.data.aerospike.query.qualifier.Qualifier;
import org.springframework.data.aerospike.query.qualifier.QualifierBuilder;
import org.springframework.data.aerospike.server.version.ServerVersionSupport;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.repository.query.parser.Part;

Expand Down Expand Up @@ -39,10 +40,12 @@ public class CollectionQueryCreator implements IAerospikeQueryCreator {
private final FilterOperation filterOperation;
private final MappingAerospikeConverter converter;
private final boolean isNested;
private final ServerVersionSupport versionSupport;

public CollectionQueryCreator(Part part, PropertyPath propertyPath, AerospikePersistentProperty property,
String fieldName, List<Object> queryParameters, FilterOperation filterOperation,
MappingAerospikeConverter converter, boolean isNested) {
MappingAerospikeConverter converter, boolean isNested,
ServerVersionSupport versionSupport) {
this.part = part;
this.propertyPath = propertyPath;
this.property = property;
Expand All @@ -51,6 +54,7 @@ public CollectionQueryCreator(Part part, PropertyPath propertyPath, AerospikePer
this.filterOperation = filterOperation;
this.converter = converter;
this.isNested = isNested;
this.versionSupport = versionSupport;
}

@Override
Expand Down Expand Up @@ -159,7 +163,7 @@ public Qualifier process() {
setQualifierBuilderValue(qb, queryParameters.get(0));
}

return setQualifier(qb, fieldName, op, part, dotPath);
return setQualifier(qb, fieldName, op, part, dotPath, versionSupport);
}

private FilterOperation getCorrespondingListFilterOperationOrFail(FilterOperation op) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ enum AerospikeNullQueryCriterion {
}

enum AerospikeMetadata {
SINCE_UPDATE_TIME, LAST_UPDATE_TIME, VOID_TIME, TTL, RECORD_SIZE_ON_DISK, RECORD_SIZE_IN_MEMORY
SINCE_UPDATE_TIME, // Exp.sinceUpdate(), milliseconds
LAST_UPDATE_TIME, // Exp.lastUpdate(), nanoseconds since epoch
VOID_TIME, // Exp.voidTime(), nanoseconds since epoch
TTL, // Exp.ttl(), integer seconds
RECORD_SIZE_ON_DISK, // Exp.deviceSize(), bytes
RECORD_SIZE_IN_MEMORY // Exp.memorySize(), bytes
}
}
Loading
Loading