当前位置: 首页 > 知识库问答 >
问题:

Hazelcast聚合API导致带有谓词的ClassCastException

宇文和昶
2023-03-14
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<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)

然后更改为使用谓词而不是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();
  }    

最后,我在尝试#3中使用了lambda来实现谓词接口:

  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的一个bug吗?似乎聚合框架应该支持由谓词谓词构建器构建的谓词?如果不是,那么应该创建一个新的类型(例如,aggregationpredicate)来避免这种混淆。

问题2(与问题1相关):使用lambda谓词会导致我创建的索引未被使用。相反,映射中的每个条目都被反序列化,以确定它是否与谓词匹配,这会大大减慢运行速度。是否有任何方法可以从使用索引的谓词创建供应商?(编辑:通过在readportable方法中放置一个计数器,我验证了每个条目都被反序列化)。

共有1个答案

贲招
2023-03-14

这看起来像榛子虫。我想我从来没有创建过unittest来测试PredicateBuilder创建的谓词。你能在GitHub上提交一个问题吗?

当前mapreduce上不支持索引,无论您尝试什么。索引系统将在不久的将来重写,以支持所有类型的非原语索引,如partial或stuff。

另一个尚不具备的是针对可移植对象的优化读取器,它将防止完全反序列化。

 类似资料:
  • 在hazelcast IMap中查找谓词结果大小的最佳方法是什么? MapProxyImpl中不支持直接大小。java和size()将根据返回的集合进行计算,在这种情况下,这是不需要的。 你有什么建议吗? 谢谢

  • 谁能告诉我如何用Hazelcast谓词“in”子句吗。我想使用以下内容, 我想将值作为值的ArrayList传递。但是它抛出错误,因为它期望实现可比的对象。对此有任何解决方法吗?

  • 我在应用程序中使用Querydsl来大大改进查询数据库的代码。但是,我有一个来自外部服务的JPA谓词(javax.persistence.criteria.Predicate)。我想混合使用Querydsl和外部谓词创建的查询。例如: 另一个解决方案是将Querydsl谓词转换为JPA谓词: 有可能吗?如果是,我如何做到这一点?如果没有,是否有其他混合谓词的解决方案(比如将两者转换为SQL字符串并

  • 我正在尝试构建一个方法,删除具有非空属性的条目,但我一直在谓词中失败,我不知道如何正确实现谓词,因为hazelcast没有将“Not NULL”或“IS NULL”作为where子句任何想法如何在映射中找到我需要搜索以删除它们的值? 方法 主类响应SerializablePlus

  • 我有一个Hazelcast地图的HashMap作为我下面所示的值。 我想使用谓词/SQLPredicate执行查询。我该怎么做? 请帮帮我。

  • 我正在创建一个自定义谓词。它需要一个整数并将其与map的值进行比较。 当我运行程序时,我得到以下错误: 我有点困惑。我需要在服务器上创建谓词吗?我以Hcast客户端运行,客户端正在创建谓词。 据我所知,在创建谓词时,它会作为序列化对象发送到hazelcast服务器。 此外,我还尝试将谓词实现为可序列化的,但没有帮助。谢谢