Let's say I have two tables in separate Ignite caches, A
and B
with the respective keys:
case class AKey(
@(QuerySqlField@field) id: Long,
@(AffinityKeyMapped@field)
@(QuerySqlField@field) parentId: Long
)
case class BKey(
@(AffinityKeyMapped@field)
@(QuerySqlField@field) aId: Long
)
Where A.parentId
is a self reference to another entry in table A
and B.aId
is reference to A.id
.
If I want all A
entries with the same parentId
to be collocated, but I also want all B
entries to be collocated with the parentId
of the referenced A
entry, how would I set up this affinity relationship without including a parentId
field in B
? Or is this impossible?
It's not clear to me from Ignite's documentation how Ignite establishes an affinity relationship between tables.
Ignite doesn't really establish any "affinity relationship". All it does is mapping of cache keys to affinity keys. All entries in all caches with the same affinity key are guaranteed to be collocated.
E.g. take caches with the following keys
class KeyA { int a1; int a2; @AffinityKeyMapped int affKey; }
class KeyB { int b1; int b2; @AffinityKeyMapped int affKey; }
Here we say that KeyA
and KeyB
are collocated via affKey
- when the values of affKey
match, the entries will be collocated. But in fact Ignite has no knowledge of connection between KeyA
and KeyB
, it processes the tables separately. Only the guarantee that the mapping of affinity key to a node is consistent makes this work. In other words, relation between this caches only exists in our heads and it is our responsibility to ensure that the collocation is correct.
Finally, on your case. It may be surprising but parentId isn't really a good candidate for affinity key. Say we have three values in A
{ id: 1, parentId: 0 }
{ id: 2, parentId: 1 }
{ id: 3, parentId: 2 }
Here one could expect all values to be collocated since all of them are referencing each other in the same "chain". But this is a relationship Ignite doesn't know about. All it knows is that there are three different parentId
values - hence, three different affinity keys and no collocation.
To correctly handle this one has to provide some groupdId
that is guaranteed to be the same across all values. A natural fit in your case would be the ID of the root element in the "tree". Then the groupdId
will be the @AffinityKeyMapped
.
{ id: 1, parentId: 0, groupId: 1 }
{ id: 2, parentId: 1, groupId: 1 }
{ id: 3, parentId: 2, groupId: 1 }
Unfortunately, the second cache has to refer to the exact same value of affinity key, and there is no way to do so without adding that as a field.
{ aId: 2, aGroupId: 1 }
Also, although it isn't related directly to the question, make sure that @AffinityKeyMapped
is a part of the cache key, not part of the value - otherwise, it will be ignored.