Home > OS >  Apache Ignite: How to get cached item without affinity key
Apache Ignite: How to get cached item without affinity key

Time:09-23

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 the createCache method).

  • Specify indexedTypes as a part of the CacheConfiguration and annotate the fields of the key and value objects as @QuerySqlField.
    The problem with indexedTypes is that you have to put annotations into classes. Obviously, this is not going to work with AffinityKey class, as you can't change it.

  • Specify QueryEntity as a part of the CacheConfiguration.
    The problem with QueryEntity 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]
  • Related