我使用Hazelcast IMap
實例來保存喜歡的對象以下內容:Hazelcast聚集API結果與謂詞
public class Report implements Portable, Comparable<Report>, Serializable
{
private String id;
private String name;
private String sourceId;
private Date timestamp;
private Map<String,Object> payload;
// ...
}
的IMap
由id
鍵,而我也sourceId
創建索引,因爲我需要根據該字段進行查詢和聚合。
IMap<String, Report> reportMap = hazelcast.getMap("reports");
reportMap.addIndex("sourceId", false);
我一直在試圖使用聚合框架,sourceId
來算報告。 嘗試#1:
public static int reportCountforSource(String sourceId)
{
EntryObject e = new PredicateBuilder().getEntryObject();
Predicate<String, Report> predicate = e.get("sourceId").equal(sourceId);
Supplier<String, Report, Object> supplier = Supplier.fromPredicate(predicate);
Long count = reportMap.aggregate(supplier, Aggregations.count());
return count.intValue();
}
這就產生了一個ClassCastException
被拋出由聚合框架:
Caused by: java.lang.ClassCastException: com.hazelcast.mapreduce.aggregation.impl.SupplierConsumingMapper$SimpleEntry cannot be cast to com.hazelcast.query.impl.QueryableEntry
at com.hazelcast.query.Predicates$AbstractPredicate.readAttribute(Predicates.java:859)
at com.hazelcast.query.Predicates$EqualPredicate.apply(Predicates.java:779)
at com.hazelcast.mapreduce.aggregation.impl.PredicateSupplier.apply(PredicateSupplier.java:58)
at com.hazelcast.mapreduce.aggregation.impl.SupplierConsumingMapper.map(SupplierConsumingMapper.java:55)
at com.hazelcast.mapreduce.impl.task.KeyValueSourceMappingPhase.executeMappingPhase(KeyValueSourceMappingPhase.java:49)
我然後改爲使用Predicates
代替PredicateBuilder().getEntryObject()
爲嘗試#2:
public static int reportCountforSource(String sourceId)
{
@SuppressWarnings("unchecked")
Predicate<String, Report> predicate = Predicates.equal("sourceId", sourceId);
Supplier<String, Report, Object> supplier = Supplier.fromPredicate(predicate);
Long count = reportMap.aggregate(supplier, Aggregations.count());
return count.intValue();
}
這導致相同的ClassCastException
。
最後,我用了一個lambda來實現嘗試#3 Predicate
接口:
public static int reportCountforSource(String sourceId)
{
Predicate<String, Report> predicate = (entry) -> entry.getValue().getSourceId().equals(sourceId);
Supplier<String, Report, Object> supplier = Supplier.fromPredicate(predicate);
Long count = reportMap.aggregate(supplier, Aggregations.count());
return count.intValue();
}
這種嘗試最終作品。
問題1:這是一個在Hazelcast中的錯誤?看起來,Aggregations框架應該支持由Predicates
或PredicateBuilder
構建的Predicate
?如果不是,則應創建新類型(例如,AggregationPredicate
)以避免這種混淆。
問題#2(與#1有關):使用lambda Predicate
會導致我創建的索引未被使用。相反,映射中的每個條目都將被反序列化以確定它是否與Predicate
相匹配,這會使事情減慢很多。有什麼辦法可以從Predicate
創建一個Supplier
來使用索引? (編輯:我通過在readPortable
方法中加入一個計數器來驗證每個條目正在被反序列化)。
感謝您的快速響應。提交:https://github.com/hazelcast/hazelcast/issues/5010 – mmindenhall
完美的感謝!讚賞。 – noctarius
該修復程序剛剛合併到Hazelcast主程序中,並將在即將發佈的3.6版本中發佈。 Thx報告它! –