Hazelcast Query API & Attribute Value Extraction

Posted by Misagh Moayyed on February 13, 2023 · 5 mins read ·
Content Unavailable
Your browser is blocking content on this website. Please check your browser settings and try again.

Hazelcast provides a Predicates API as a programming interface for querying data in Hazelcast maps. This API can accept SQL-like queries that can be used to fetch or locate data in Hazelcast maps. In this post, we will focus on how the Hazelcast query language may be extended to allow for querying custom attributes inside a Java-based entity that stores data inside a HashMap.

This tutorial specifically requires and focuses on:

  • Hazelcast 5.2.x
  • Java 17

Use Case

The Hazelcast Predicates SQL API generally has the following structure:

var query = "...";
var results = hazelcastMapInstance.values(Predicates.sql(query));

Furthermore, let’s consider that entities and objects that are stored inside our hazelcastMapInstance are represented using the following data model:

class Model {
    private Map<String, List<String>> attributes = new HashMap<>();
}

Our SQL statement should return results for the following query:

Find all Model objects in the Hazelcast map that have an entry with the key uid whose values may contain test.

In a sense, our SQL query should be able to support the following syntax:

var query = "attributes[uid] IN ('test')";
var results = hazelcastMapInstance.values(Predicates.sql(query));

Hazelcast ValueExtractor

To extract a custom attribute, that is attributes[uid], we should take advantage of com.hazelcast.query.extractor.ValueExtractor. Our implementation should encompass the extraction logic to look for a custom argument inside the map, capture its values and pass those back to Hazelcast’s value collector.

@Override
public void extract(final Model model,
                    final String attributeName,
                    final ValueCollector valueCollector) {
    var values = model.getAttributes().get(attributeName);
    if (values != null) {
        valueCollector.addObject(new MultiResult<>(values));
    }
}

We should also of course register our extractor with Hazelcast:

var attributeConfig = new AttributeConfig();
attributeConfig.setName("attributes");
attributeConfig.setExtractorClassName("...");

var mapConfig = new MapConfig();
mapConfig.addAttributeConfig(attributeConfig);

Keep in mind that an extractor may not be added after the map has been instantiated. All extractors have to be defined upfront in the map’s initial configuration.

Need Help?

If you have questions about the contents and the topic of this blog post, or if you need additional guidance and support, feel free to send us a note and ask about consulting and support services.

So…

I hope this review was of some help to you and I am sure that both this post as well as the functionality it attempts to explain can be improved in any number of ways. Please feel free to engage and contribute as best as you can.

Happy Coding,

Misagh Moayyed