[[redis.repositories.anatomy]]
= Redis Repositories Anatomy

Redis as a store itself offers a very narrow low-level API leaving higher level functions, such as secondary indexes and query operations, up to the user.

This section provides a more detailed view of commands issued by the repository abstraction for a better understanding of potential performance implications.

Consider the following entity class as the starting point for all operations:

.Example entity
====
[source,java]
----
@RedisHash("people")
public class Person {

  @Id String id;
  @Indexed String firstname;
  String lastname;
  Address hometown;
}

public class Address {

  @GeoIndexed Point location;
}
----
====

[[redis.repositories.anatomy.insert]]
== Insert new

====
[source,java]
----
repository.save(new Person("rand", "al'thor"));
----

[source,text]
----
HMSET "people:19315449-cda2-4f5c-b696-9cb8018fa1f9" "_class" "Person" "id" "19315449-cda2-4f5c-b696-9cb8018fa1f9" "firstname" "rand" "lastname" "al'thor" <1>
SADD  "people" "19315449-cda2-4f5c-b696-9cb8018fa1f9"                           <2>
SADD  "people:firstname:rand" "19315449-cda2-4f5c-b696-9cb8018fa1f9"            <3>
SADD  "people:19315449-cda2-4f5c-b696-9cb8018fa1f9:idx" "people:firstname:rand" <4>
----

<1> Save the flattened entry as hash.
<2> Add the key of the hash written in <1> to the helper index of entities in the same keyspace.
<3> Add the key of the hash written in <2> to the secondary index of firstnames with the properties value.
<4> Add the index of <3> to the set of helper structures for entry to keep track of indexes to clean on delete/update.
====

[[redis.repositories.anatomy.replace]]
== Replace existing

====
[source,java]
----
repository.save(new Person("e82908cf-e7d3-47c2-9eec-b4e0967ad0c9", "Dragon Reborn", "al'thor"));
----

[source,text]
----
DEL       "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9"                           <1>
HMSET     "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9" "_class" "Person" "id" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9" "firstname" "Dragon Reborn" "lastname" "al'thor" <2>
SADD      "people" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9"                         <3>
SMEMBERS  "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9:idx"                       <4>
TYPE      "people:firstname:rand"                                                 <5>
SREM      "people:firstname:rand" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9"          <6>
DEL       "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9:idx"                       <7>
SADD      "people:firstname:Dragon Reborn" "e82908cf-e7d3-47c2-9eec-b4e0967ad0c9" <8>
SADD      "people:e82908cf-e7d3-47c2-9eec-b4e0967ad0c9:idx" "people:firstname:Dragon Reborn" <9>
----

<1> Remove the existing hash to avoid leftovers of hash keys potentially no longer present.
<2> Save the flattened entry as hash.
<3> Add the key of the hash written in <1> to the helper index of entities in the same keyspace.
<4> Get existing index structures that might need to be updated.
<5> Check if the index exists and what type it is (text, geo, …).
<6> Remove a potentially existing key from the index.
<7> Remove the helper holding index information.
<8> Add the key of the hash added in <2> to the secondary index of firstnames with the properties value.
<9> Add the index of <6> to the set of helper structures for entry to keep track of indexes to clean on delete/update.
====

[[redis.repositories.anatomy.geo]]
== Save Geo Data

Geo indexes follow the same rules as normal text based ones but use geo structure to store values.
Saving an entity that uses a Geo-indexed property results in the following commands:

====
[source,text]
----
GEOADD "people:hometown:location" "13.361389" "38.115556" "76900e94-b057-44bc-abcf-8126d51a621b"  <1>
SADD   "people:76900e94-b057-44bc-abcf-8126d51a621b:idx" "people:hometown:location"               <2>
----

<1> Add the key of the saved entry to the the geo index.
<2> Keep track of the index structure.
====

[[redis.repositories.anatomy.index]]
== Find using simple index

====
[source,java]
----
repository.findByFirstname("egwene");
----

[source,text]
----
SINTER  "people:firstname:egwene"                     <1>
HGETALL "people:d70091b5-0b9a-4c0a-9551-519e61bc9ef3" <2>
HGETALL ...
----

<1> Fetch keys contained in the secondary index.
<2> Fetch each key returned by <1> individually.
====

[[redis.repositories.anatomy.geo-index]]
== Find using Geo Index

====
[source,java]
----
repository.findByHometownLocationNear(new Point(15, 37), new Distance(200, KILOMETERS));
----

[source,text]
----
GEORADIUS "people:hometown:location" "15.0" "37.0" "200.0" "km" <1>
HGETALL   "people:76900e94-b057-44bc-abcf-8126d51a621b"         <2>
HGETALL   ...
----

<1> Fetch keys contained in the secondary index.
<2> Fetch each key returned by <1> individually.
====
