We now enable storing domain object as a flat Redis 'HASH' and maintain additional 'SET' structures to enable finder operations on simple properties.
@RedisHash("persons");
class Person {
@id String id;
@Indexed String firstname;
String lastname;
Map<String, String> attributes;
City city;
@Reference Person mother;
}
The above is stored in the HASH with key 'persons:1' as
_class = org.example.Person
id = 1
firstname = rand
lastname = al’thor
attributes.[eye-color] = grey
attributes.[hair-color] = red
city.name = emond's field
city.region = two rivers
mother = persons:2
Complex types are flattened out to their full property path for each of the values provided. If the properties actual value type does not match the declared one the '_class' type hint is added to the entry.
city._class = CityInAndor.class
city.name = emond's field
city.region = two rivers
city.country = andor
Map and Collection like structures are stored with their key/index values as part of the property path. If the map/collection value type does not match the actutal objects one the '_class' type hint is added to the entry.
list.[0]._class = DomainType.class
list.[0].property1 = ...
map.[key-1]._class = DomainType.class
map.[key-1].property1 = ...
Properties marked with '@Reference' are stored as semantic references by just storing the key to the referenced object 'HASH' instead of embedding its values.
mother = persons:2
Please note that referenced objects are not transitively updated/saved and that lazy loading of references will be part of future development.
A 'save' operation therefore executes the following:
# flatten domain type and add as hash
HMSET persons:1 id 1 firstname rand …
# add the newly inserted entry to the list of all entries of that type
SADD persons 1
# index the firstname for finder lookup
SADD persons.firstname:rand 1
Simple finder operation like 'findByFirstname' use 'SINTER' to find matching
SINTER persons.firstname:rand
HGETALL persons:1
Besides resolving an index via the '@Index' annotation we also allow to add custom configuration via the 'indexConfiguration' attribute of '@EnableRedisRepositories'.
@Configuration
@EnableRedisRepositories(indexConfiguration = CustomIndexConfiguration.class)
class Config { }
static class CustomIndexConfiguration extends IndexConfiguration {
@Override
protected Iterable<RedisIndexDefinition> initialConfiguration() {
return Arrays.asList(
new SimpleIndexDefinition("persons", "lastname"),
);
}
}
The '@TimeToLive' annotation allows to define a property or method providing an expiration time when storing the key in redis.
@RedisHash
class Person {
@Id String id;
@TimeToLive Long ttl;
}
Original Pull Request: #156