I have two caches, one is for Person and another is for Company objects, By specifying the Person.Id as the key and Person.CompanyId as the affinity key.
personCache.Put(new AffinityKey(p1.Id, p1.CompanyId), p1);
companyCache.Put(c1.Id, c1);
Is it possible to get the person from the cache using Person.Id? (without having Person.CompanyId)?
CodePudding user response:
Yes, but not with Key-Value API.
Key-Value API, by definition, requires a key to access the data. If your key is AffinityKey(personId, companyId)
then you have to construct the full key object in order to use the IgniteCache::get
operation.
However, there is also SQL API which is another interface to access the same data. You can declare the cache as an SQL-enabled cache and the personId
as an SQL field in that cache.
There are multiple ways to create an SQL-enabled cache:
Create it with the
CREATE TABLE
statement (as opposed to specifying it in the node config or creating with thecreateCache
method).Specify
indexedTypes
as a part of theCacheConfiguration
and annotate the fields of the key and value objects as@QuerySqlField
.
The problem withindexedTypes
is that you have to put annotations into classes. Obviously, this is not going to work withAffinityKey
class, as you can't change it.Specify
QueryEntity
as a part of theCacheConfiguration
.
The problem withQueryEntity
is that it may get pretty complex, and it's generally a bit harder to maintain then@QuerySqlField
annotations.
In your case, I would recommend not to use AffinityKey
class and create your own version of it - let's call it PersonKey
. You can annotate its fields and use indexedTypes
.
Below is a short example:
public class SqlFieldInKeyExample {
static class PersonKey {
@QuerySqlField
long personId;
@QuerySqlField
@AffinityKeyMapped
long companyId;
public PersonKey(long personId, long companyId) {
this.personId = personId;
this.companyId = companyId;
}
}
static class Person {
@QuerySqlField
String name;
public Person(String name) {
this.name = name;
}
}
public static void main(String[] args) throws IgniteException {
try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) {
CacheConfiguration<PersonKey, Person> cfg = new CacheConfiguration<PersonKey, Person>()
.setName("PersonCache")
.setIndexedTypes(PersonKey.class, Person.class);
IgniteCache<PersonKey, Person> cache = ignite.createCache(cfg);
cache.put(new PersonKey(9000, 42), new Person("John Doe"));
List<List<?>> result = cache.query(new SqlFieldsQuery("SELECT * FROM PERSON WHERE PERSONID = 9000")).getAll();
assert result.size() == 1;
System.out.println(">>>>> Person: " result.get(0));
}
}
}
Output (among other things) is:
>>>>> Person: [9000, 42, John Doe]