Query

The Cache<K,V> supports queries, allowing you to locate objects in the store that satisfy a filter expression.

Enumerating over the Iterable<V> instance returned by Cache.queryObjects() allows you to iterate over every object stored in a cache. For large caches this will be slow and computationally expensively. To alleviate the expensive nature of queries, the query request can provide a filter (or a chain of filters) to the in-memory data grid to only match objects that satisfy the filter (or chain of filters).

In order to execute the cache.queryKeys() and cache.queryObjects() methods, objects stored in the cache should annotate the properties that are queryable. To do this, define a property on a class member in the ScaleOut service by using the @CacheObjectAttribute annotation. During any add, or update method, the cache will introspect on the object and create a representation of the annotated methods as simple properties that the in-memory data grid will use when processing the filter (or chain of filters).

Each annotated property on an object can optionally supply a HashIndexPriority. The HashIndexPriority indicates the priority of an item annotated with <code>CacheObjectAttribute</code> for using the limited slots (8 total slots) in the in-memory data grid property index hash table. Even if there’s no room for an item in the hash table, the item will still be entered into the property index.

Filters

Inside the Java ScaleOut Client “query” package, the FilterFactory class can be used to instantiate different filters. For example, if the application wanted to create a filter that would match objects with a member variable in a range of values then you can use the FilterFactory.greaterThan() and FilterFactory.lessThan() filters.

Similarly, filters can be chained together using logical operators like FilterFactory.and(), FilterFactory.or(), and FilterFactory.not().

Example

Start by creating an object and annotating the methods of the class that we want to be able to query. For example:

public class SampleObject implements Serializable {
        private int _sampleNum;
        private double _sampleDouble;
        private int _ignoredNum;
        public SampleObject(int num, double dub) {
                _sampleNum              = num;
                _sampleDouble   = dub;
        }

        @CacheObjectAttribute
        public int getSampleNum() {
                return _sampleNum;
        }

        @CacheObjectAttribute(HashIndexPriority.HighPriorityHashable)
        public double getSampleDouble() {
                return _sampleDouble;
        }

        public int getIgnoredNum() {
                return _ignoredNum;
        }
}

Note that the getSampleNum() and getSampleDouble() methods are annotated with the @CacheObjectAttribute and the getIgnoredNum() method is not annoted. Only the getSampleNum() and getSampleDouble() methods can be used for query.

Next, we’ll want to query these objects. Let’s create a query that filters the result of both values. In the following sample, the filter will match objects that have getSampleNum() returning 5 and getSampleDouble() returning .23d:

GridConnection connection = GridConnection.connect("bootstrapGateways=10.0.4.248:12724;maxServerConn=4;usesecure=true;ignorekeyappid=false;");

Cache<UUID,SampleClass> cache = new CacheBuilder<UUID,TestObject>(connection,"example", UUID.class).build();

cache.queryKeys( and(equal("getTestNum", 5), equal("getTestDouble", 0.23d)), SampleClass.class);