Skip to content

Commit

Permalink
FMWK-156 Further support for deeply nested fields (#515)
Browse files Browse the repository at this point in the history
  • Loading branch information
agrgr authored Apr 4, 2023
1 parent 9169acd commit 7612ffb
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 79 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public InternalIndexOperations(IndexInfoParser indexInfoParser) {

private static IndexKey getIndexKey(Index index) {
return new IndexKey(index.getNamespace(), index.getSet(), index.getBin(), index.getType(),
index.getCollectionType());
index.getCollectionType(), index.getCTX());
}

public IndexesInfo parseIndexesInfo(String infoResponse) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
*/
package org.springframework.data.aerospike.query.model;

import com.aerospike.client.cdt.CTX;
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.IndexType;

import java.util.Arrays;
import java.util.Objects;

/**
Expand All @@ -30,6 +32,7 @@ public class IndexKey {
private final String field;
private final IndexType type;
private final IndexCollectionType collectionType;
private CTX[] ctx;

public IndexKey(String namespace, String set, String field, IndexType type, IndexCollectionType collectionType) {
this.namespace = namespace;
Expand All @@ -39,6 +42,16 @@ public IndexKey(String namespace, String set, String field, IndexType type, Inde
this.collectionType = collectionType;
}

public IndexKey(String namespace, String set, String field, IndexType type, IndexCollectionType collectionType,
CTX[] ctx) {
this.namespace = namespace;
this.set = set;
this.field = field;
this.type = type;
this.collectionType = collectionType;
this.ctx = ctx;
}

public String getNamespace() {
return namespace;
}
Expand All @@ -59,6 +72,10 @@ public IndexCollectionType getCollectionType() {
return collectionType;
}

public CTX[] getCTX() {
return ctx;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -68,12 +85,13 @@ public boolean equals(Object o) {
Objects.equals(set, indexKey.set) &&
Objects.equals(field, indexKey.field) &&
type == indexKey.type &&
collectionType == indexKey.collectionType;
collectionType == indexKey.collectionType &&
ctx == indexKey.ctx;
}

@Override
public int hashCode() {
return Objects.hash(namespace, set, field, type, collectionType);
return Objects.hash(namespace, set, field, type, collectionType, ctx);
}

@Override
Expand All @@ -84,6 +102,7 @@ public String toString() {
", field='" + field + '\'' +
", type=" + type +
", collectionType=" + collectionType +
", ctx=" + Arrays.toString(ctx) +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ private AerospikeCriteria create(Part part, AerospikePersistentProperty property
case NOTEQ:
op = FilterOperation.MAP_VALUE_NOTEQ_BY_KEY;
setQbValuesForMapByKey(qb, v1, next);
qb.setDotPath(part.getProperty().toDotPath());
break;
case GT:
op = FilterOperation.MAP_VALUE_GT_BY_KEY;
Expand Down Expand Up @@ -229,6 +230,8 @@ private AerospikeCriteria create(Part part, AerospikePersistentProperty property
qb.setValue3(Value.get(next)); // contains upper limit (inclusive)
break;
}
fieldName = part.getProperty().getSegment(); // Map bin name, later passed to Exp.mapBin()
qb.setDotPath(part.getProperty().toDotPath() + "." + Value.get(v1));
} else if (params.size() == 0) {
fieldName = part.getProperty().getSegment(); // Map bin name, later passed to Exp.mapBin()
qb.setValue2(Value.get(property.getFieldName())); // VALUE2 contains key (field name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.aerospike.client.IAerospikeClient;
import com.aerospike.client.Key;
import com.aerospike.client.Record;
import com.aerospike.client.cdt.CTX;
import com.aerospike.client.policy.Policy;
import com.aerospike.client.policy.RecordExistsAction;
import com.aerospike.client.policy.WritePolicy;
Expand Down Expand Up @@ -92,6 +93,12 @@ private void awaitUntilSetIsEmpty(Class<?> entityClass) {
.until(() -> isEntityClassSetEmpty(entityClass));
}

public <T> void createIndexIfNotExists(Class<T> entityClass, String indexName, String binName,
IndexType indexType, IndexCollectionType indexCollectionType, CTX... ctx) {
IndexUtils.createIndex(client, getNamespace(), getSetName(entityClass), indexName, binName, indexType,
indexCollectionType, ctx);
}

public <T> void createIndexIfNotExists(Class<T> entityClass, String indexName, String binName,
IndexType indexType, IndexCollectionType indexCollectionType) {
IndexUtils.createIndex(client, getNamespace(), getSetName(entityClass), indexName, binName, indexType,
Expand Down
16 changes: 15 additions & 1 deletion src/test/java/org/springframework/data/aerospike/IndexUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.aerospike.client.IAerospikeClient;
import com.aerospike.client.Info;
import com.aerospike.client.ResultCode;
import com.aerospike.client.cdt.CTX;
import com.aerospike.client.cluster.Node;
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.IndexType;
Expand Down Expand Up @@ -31,7 +32,7 @@ public static void dropIndex(IAerospikeClient client, String namespace, String s
}
}

public static void createIndex(IAerospikeClient client, String namespace, String setName, String indexName,
public static void createIndex(IAerospikeClient client, String namespace, String setName, String indexName,
String binName, IndexType indexType) {
if (IndexUtils.isDropCreateBehaviorUpdated(client)) {
waitTillComplete(() -> client.createIndex(null, namespace, setName, indexName, binName, indexType));
Expand All @@ -54,6 +55,19 @@ public static void createIndex(IAerospikeClient client, String namespace, String
}
}

public static void createIndex(IAerospikeClient client, String namespace, String setName, String indexName,
String binName, IndexType indexType, IndexCollectionType collectionType,
CTX[] ctx) {
if (IndexUtils.isDropCreateBehaviorUpdated(client)) {
waitTillComplete(() -> client.createIndex(null, namespace, setName, indexName, binName, indexType,
collectionType, ctx));
} else {
// ignoring ResultCode.INDEX_ALREADY_EXISTS for Aerospike Server prior to ver. 6.1.0.1
ignoreErrorAndWait(ResultCode.INDEX_ALREADY_EXISTS, () -> client.createIndex(null, namespace, setName,
indexName, binName, indexType, collectionType, ctx));
}
}

public static List<Index> getIndexes(IAerospikeClient client, String namespace, IndexInfoParser indexInfoParser) {
Node node = client.getCluster().getRandomNode();
String response = Info.request(node, "sindex-list:ns=" + namespace + ";b64=true");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.springframework.data.aerospike.repository;

import com.aerospike.client.Value;
import com.aerospike.client.cdt.CTX;
import com.aerospike.client.query.IndexCollectionType;
import com.aerospike.client.query.IndexType;
import org.junit.jupiter.api.AfterAll;
Expand Down Expand Up @@ -57,6 +59,12 @@ public void afterAll() {
additionalAerospikeTestOperations.dropIndexIfExists(IndexedPerson.class, "indexed_person_int_map_values_index");
additionalAerospikeTestOperations.dropIndexIfExists(IndexedPerson.class, "indexed_person_address_keys_index");
additionalAerospikeTestOperations.dropIndexIfExists(IndexedPerson.class, "indexed_person_address_values_index");
additionalAerospikeTestOperations.dropIndexIfExists(IndexedPerson.class,
"indexed_person_friend_address_keys_index");
additionalAerospikeTestOperations.dropIndexIfExists(IndexedPerson.class,
"indexed_person_friend_address_values_index");
additionalAerospikeTestOperations.dropIndexIfExists(IndexedPerson.class,
"indexed_person_friend_bestFriend_address_keys_index");
indexRefresher.clearCache();
}

Expand Down Expand Up @@ -88,6 +96,15 @@ public void beforeAll() {
"indexed_person_address_keys_index", "address", IndexType.STRING, IndexCollectionType.MAPKEYS);
additionalAerospikeTestOperations.createIndexIfNotExists(IndexedPerson.class,
"indexed_person_address_values_index", "address", IndexType.STRING, IndexCollectionType.MAPVALUES);
additionalAerospikeTestOperations.createIndexIfNotExists(IndexedPerson.class,
"indexed_person_friend_address_keys_index", "friend", IndexType.STRING,
IndexCollectionType.MAPKEYS, CTX.mapKey(Value.get("address")));
additionalAerospikeTestOperations.createIndexIfNotExists(IndexedPerson.class,
"indexed_person_friend_address_values_index", "friend", IndexType.STRING,
IndexCollectionType.MAPVALUES, CTX.mapValue(Value.get("address")));
additionalAerospikeTestOperations.createIndexIfNotExists(IndexedPerson.class,
"indexed_person_friend_bestFriend_address_keys_index", "friend", IndexType.STRING,
IndexCollectionType.MAPKEYS, CTX.mapKey(Value.get("bestFriend")), CTX.mapKey(Value.get("address")));
indexRefresher.refreshIndexes();
}

Expand Down Expand Up @@ -318,7 +335,6 @@ void findByMapKeysContaining() {

List<IndexedPerson> persons = repository.findByStringMapContaining("key1",
CriteriaDefinition.AerospikeMapCriteria.KEY);

assertThat(persons).contains(stefan, boyd);
}

Expand All @@ -329,7 +345,6 @@ void findByMapValuesContaining() {

List<IndexedPerson> persons = repository.findByStringMapContaining("val1",
CriteriaDefinition.AerospikeMapCriteria.VALUE);

assertThat(persons).contains(stefan, boyd);
}

Expand All @@ -339,7 +354,6 @@ void findByMapKeyValueEqualsInt() {
assertThat(leroi.getIntMap()).containsValue(0);

Iterable<IndexedPerson> result = repository.findByIntMapEquals("key1", 0);

assertThat(result).contains(leroi);
}

Expand All @@ -351,24 +365,59 @@ void findByMapKeyValueEqualsString() {
assertThat(boyd.getStringMap()).containsValue("val1");

List<IndexedPerson> persons = repository.findByStringMapEquals("key1", "val1");

assertThat(persons).contains(stefan, boyd);
}

@Test
void findPersonsByAddressZipCode() {
assertThat(dave.getAddress().getZipCode()).isEqualTo("C0123");
List<IndexedPerson> result = repository.findByAddressZipCode("C0123");

assertThat(result).contains(dave);
}

@Test
void findPersonsByFriendAddressZipCode() {
assertThat(dave.getAddress().getZipCode()).isEqualTo("C0123");
carter.setFriend(dave);
repository.save(carter);

List<IndexedPerson> result = repository.findByFriendAddressZipCode("C0123");
assertThat(result).contains(carter);
setFriendsToNull(carter);
}

@Test
void findPersonsByFriendBestFriendAddressZipCode() {
assertThat(dave.getAddress().getZipCode()).isEqualTo("C0123");
carter.setBestFriend(dave);
repository.save(carter);
donny.setFriend(carter);
repository.save(donny);

List<IndexedPerson> result = repository.findByFriendBestFriendAddressZipCode("C0123");
assertThat(result).contains(donny);
setFriendsToNull(carter, donny);
}

@Test
void findPersonsByFriendBestFriendAddressApartment() {
assertThat(dave.getAddress().getApartment()).isEqualTo(1);
carter.setBestFriend(dave);
repository.save(carter);
donny.setFriend(carter);
repository.save(donny);

List<IndexedPerson> result = repository.findByFriendBestFriendAddressApartment(1);
assertThat(result).contains(donny);
setFriendsToNull(carter, donny);
}

@Test
void findByMapKeyValueGreaterThan() {
assertThat(leroi.getIntMap()).containsKey("key2");
assertThat(leroi.getIntMap().get("key2") > 0).isTrue();

List<IndexedPerson> persons = repository.findByIntMapGreaterThan("key2", 0);

assertThat(persons).contains(leroi);
}

Expand All @@ -378,7 +427,6 @@ void findByMapKeyValueLessThanOrEqual() {
assertThat(leroi.getIntMap().get("key2") > 0).isTrue();

List<IndexedPerson> persons = repository.findByIntMapLessThanEqual("key2", 1);

assertThat(persons).containsExactlyInAnyOrder(leroi, carter);
}

Expand All @@ -390,7 +438,49 @@ void findByMapKeyValueBetween() {
assertThat(leroi.getIntMap().get("key2") >= 0).isTrue();

List<IndexedPerson> persons = repository.findByIntMapBetween("key2", 0, 1);

assertThat(persons).containsExactlyInAnyOrder(leroi, carter);
}

@Test
void findByBestFriendFriendIntMapKeyValueBetween() {
assertThat(leroi.getIntMap()).containsKey("key2");
assertThat(leroi.getIntMap().get("key2") >= 0).isTrue();

carter.setFriend(leroi);
repository.save(carter);
leroi2.setBestFriend(carter);

repository.save(leroi2);

List<IndexedPerson> persons = repository.findByBestFriendFriendIntMapBetween("key2", 0, 1);
assertThat(persons).contains(leroi2);

setFriendsToNull(carter, leroi2);
}

@Test
void findByBestFriendFriendAddressApartmentBetween() {
assertThat(carter.getAddress().getApartment()).isEqualTo(2);

leroi.setFriend(carter);
repository.save(leroi);
leroi2.setBestFriend(leroi);
repository.save(leroi2);

List<IndexedPerson> persons = repository.findByBestFriendFriendAddressApartmentBetween(1, 2);
assertThat(persons).contains(leroi2);

setFriendsToNull(leroi, leroi2);
}

private void setFriendsToNull(IndexedPerson... persons) {
for (IndexedPerson person : persons) {
person.setFriend(null);
repository.save(person);
}
for (IndexedPerson person : persons) {
person.setBestFriend(null);
repository.save(person);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,15 @@ void findByMapKeyValueBetween() {
}

@Test
void findByDateOfBirthBefore() {
dave.setDateOfBirth(new Date());
void findByRegDateBefore() {
dave.setRegDate(LocalDate.of(1980, 3, 10));
repository.save(dave);

List<Person> persons = repository.findByDateOfBirthBefore(new Date());
List<Person> persons = repository.findByRegDateBefore(LocalDate.of(1981, 3, 10));
assertThat(persons).contains(dave);

dave.setDateOfBirth(null);
repository.save(dave);
}

@Test
Expand All @@ -259,16 +262,22 @@ void findByDateOfBirthAfter() {

List<Person> persons = repository.findByDateOfBirthAfter(new Date(126230400));
assertThat(persons).contains(dave);

dave.setDateOfBirth(null);
repository.save(dave);
}

@Test
void findByRegDate() {
LocalDate date = LocalDate.of(1982, 3, 10);
LocalDate date = LocalDate.of(1970, 3, 10);
carter.setRegDate(date);
repository.save(carter);

List<Person> persons = repository.findByRegDate(date);
assertThat(persons).contains(carter);

carter.setRegDate(null);
repository.save(carter);
}

@Test
Expand Down
Loading

0 comments on commit 7612ffb

Please sign in to comment.