Nilesh Barai
Nilesh Barai

Reputation: 1322

Hazelcast distributed query using indexes

I am trying to query Hazelcast map using predicates. My predicate code works fine without indexes but for better performance, I want to put index on the key my Hazelcast map.

Map Structure: IMap<Event, Long> - Event is a POJO class.

<map name="event.map">
  <in-memory-format>NATIVE</in-memory-format>
  <backup-count>2</backup-count>
  <async-backup-count>0</async-backup-count>
  <time-to-live-seconds>30</time-to-live-seconds>
  <max-idle-seconds>0</max-idle-seconds>
  <eviction-policy>LFU</eviction-policy>
  <max-size policy="FREE_NATIVE_MEMORY_PERCENTAGE">25</max-size>
  <cache-deserialized-values>INDEX-ONLY</cache-deserialized-values>
  <indexes>
    <index ordered="true">eventType</index>
</indexes>
</map>

With the above Map config, I get following exception:

Jul 19, 2019 10:04:21 PM com.hazelcast.map.impl.operation.HDEntryOperation
SEVERE: [127.0.0.1]:5701 [dev] [3.11.2] java.lang.IllegalArgumentException: There is no suitable accessor for 'eventType' on class 'java.lang.Long'
com.hazelcast.query.QueryException: java.lang.IllegalArgumentException: There is no suitable accessor for 'eventType' on class 'java.lang.Long'
        at com.hazelcast.query.impl.getters.ReflectionHelper.createGetter(ReflectionHelper.java:175)
        at com.hazelcast.query.impl.getters.Extractors.instantiateGetter(Extractors.java:124)
        at com.hazelcast.query.impl.getters.Extractors.getGetter(Extractors.java:101)
        at com.hazelcast.query.impl.getters.Extractors.extract(Extractors.java:63)
        at com.hazelcast.query.impl.QueryableEntry.extractAttributeValueFromTargetObject(QueryableEntry.java:144)
        at com.hazelcast.query.impl.QueryableEntry.extractAttributeValue(QueryableEntry.java:82)
        at com.hazelcast.query.impl.QueryableEntry.getAttributeValue(QueryableEntry.java:48)
        at com.hazelcast.query.impl.QueryableEntry.getConverter(QueryableEntry.java:67)
        at com.hazelcast.query.impl.IndexImpl.saveEntryIndex(IndexImpl.java:79)
        at com.hazelcast.query.impl.Indexes.saveEntryIndex(Indexes.java:164)
        at com.hazelcast.map.impl.recordstore.AbstractRecordStore.saveIndex(AbstractRecordStore.java:165)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.putInternal(DefaultRecordStore.java:709)
        at com.hazelcast.map.impl.recordstore.DefaultRecordStore.setWithUncountedAccess(DefaultRecordStore.java:987)
        at com.hazelcast.map.impl.operation.EntryOperator.onAddedOrUpdated(EntryOperator.java:288)
        at com.hazelcast.map.impl.operation.EntryOperator.doPostOperateOps(EntryOperator.java:219)
        at com.hazelcast.map.impl.operation.HDEntryOperation.runVanilla(HDEntryOperation.java:257)
        at com.hazelcast.map.impl.operation.HDEntryOperation.runInternal(HDEntryOperation.java:95)
        at com.hazelcast.map.impl.operation.HDMapOperation.run(HDMapOperation.java:88)
        at com.hazelcast.spi.Operation.call(Operation.java:170)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:208)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:197)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationExecutorImpl.run(OperationExecutorImpl.java:407)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationExecutorImpl.runOrExecute(OperationExecutorImpl.java:434)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvokeLocal(Invocation.java:586)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.doInvoke(Invocation.java:571)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke0(Invocation.java:530)
        at com.hazelcast.spi.impl.operationservice.impl.Invocation.invoke(Invocation.java:220)
        at com.hazelcast.spi.impl.operationservice.impl.InvocationBuilderImpl.invoke(InvocationBuilderImpl.java:60)
        at com.hazelcast.client.impl.protocol.task.AbstractPartitionMessageTask.processMessage(AbstractPartitionMessageTask.java:67)
        at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.initializeAndProcessMessage(AbstractMessageTask.java:123)
        at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.doRun(AbstractMessageTask.java:111)
        at com.hazelcast.client.impl.protocol.task.AbstractMessageTask.run(AbstractMessageTask.java:101)
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:161)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:159)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:127)
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:110)
Caused by: java.lang.IllegalArgumentException: There is no suitable accessor for 'eventType' on class 'java.lang.Long'
        at com.hazelcast.query.impl.getters.ReflectionHelper.createGetter(ReflectionHelper.java:168)
        ... 35 more

From the exception I understand that Hazelcast is trying to apply the index on the Value field of the IMap.

Is there a way index can be put on the Key field of the IMap?

Upvotes: 1

Views: 1850

Answers (1)

Neil Stevenson
Neil Stevenson

Reputation: 3150

Try

        <indexes>
            <index ordered="true">__key.eventType</index>
        </indexes>

As a key-value store, it's usual to search on the values, so that's what the index expects. When you put eventType in the index it looks for that field in the value. You need to change it to __key.eventType to make it look in the key.

If you need frequent search access to part of a composite primary key, as the index implements, then the choice of primary key structure may need reviewed.

Also, if you can, upgrade from 3.11.2 to 3.12.1. There are some querying improvements behind the scenes.

Upvotes: 1

Related Questions