Cassandra:带有地图结果的 UDF 在 Java 中获取 CodecNotFoundException

Posted

技术标签:

【中文标题】Cassandra:带有地图结果的 UDF 在 Java 中获取 CodecNotFoundException【英文标题】:Cassandra: UDF with map result gets CodecNotFoundException in Java 【发布时间】:2016-11-01 22:39:14 【问题描述】:

使用自定义聚合函数执行查询时,有时会在 Java 驱动程序中遇到 com.datastax.driver.core.exceptions.CodecNotFoundException 异常。

聚合函数的结果是一个map。我希望 Java API 会有一个用于标准类型映射的编解码器。

cqlsh 也报错“Failed to format value OrderedMapSerializedKey”,但是以 JSON 格式显示数据。

最终的功能是:

CREATE OR REPLACE FUNCTION average_by_source_final_1( state avg_type_1)
    CALLED ON NULL INPUT
    RETURNS map<text,double>
    LANGUAGE java
    ...

聚合为:

CREATE OR REPLACE AGGREGATE avg_by_source( text, double)
    SFUNC average_by_source_1
    STYPE avg_type_1
    FINALFUNC average_by_source_final_1
    INITCOND ((null, 0, 0.0), null)
;

我假设最终函数的返回类型需要编解码器,而不是 STYPE。

Java 的异常:

execution of 'average_by_source_1[avg_type_1, text, double]' failed: com.datastax.driver.core.exceptions.CodecNotFoundException
... com.datastax.driver.core.exceptions.FunctionExecutionException: execution of 'roger_ts_08.average_by_source_1[avg_type_1, text, double]' failed: com.datasta
x.driver.core.exceptions.CodecNotFoundException
        at com.datastax.driver.core.exceptions.FunctionExecutionException.copy(FunctionExecutionException.java:58)
        at com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:37)
        at com.datastax.driver.core.DefaultResultSetFuture.getUninterruptibly(DefaultResultSetFuture.java:245)
        at com.datastax.driver.core.AbstractSession.execute(AbstractSession.java:64)
        at com.brocade.tspoc.CassandraDb.aggregateWithAggrFunc(CassandraDb.java:309)
        at com.brocade.tspoc.Main.aggregateWithAggrFuncTest(Main.java:223)
        at com.brocade.tspoc.Main.main(Main.java:42)
Caused by: com.datastax.driver.core.exceptions.FunctionExecutionException: execution of 'average_by_source_1[avg_type_1, text, double]' failed: com.datastax.driver.core.exceptions.CodecNotFoundException
        at com.datastax.driver.core.Responses$Error.asException(Responses.java:130)
        at com.datastax.driver.core.DefaultResultSetFuture.onSet(DefaultResultSetFuture.java:179)
        at com.datastax.driver.core.RequestHandler.setFinalResult(RequestHandler.java:174)
        at com.datastax.driver.core.RequestHandler.access$2600(RequestHandler.java:43)
        at com.datastax.driver.core.RequestHandler$SpeculativeExecution.setFinalResult(RequestHandler.java:793)
        at com.datastax.driver.core.RequestHandler$SpeculativeExecution.onSet(RequestHandler.java:627)
        at com.datastax.driver.core.Connection$Dispatcher.channelRead0(Connection.java:1012)

在 cqlsh 中:

 avg_by_source(source, value)
----------------------------------------------------------------------------------------------------

 OrderedMapSerializedKey([(u'i1', 23.5), (u'i2', 1.2), (u's1', 50.0), (u's2', 15.0), (u's3', 8.0)])

(1 rows)
Failed to format value OrderedMapSerializedKey([(u'i1', 23.5), (u'i2', 1.2), (u's1', 50.0), (u's2', 15.0), (u's3', 8.0)]) : 'NoneType' object has no attribute 'sub_types'

【问题讨论】:

cqlsh 部分似乎是由最近修复的错误CASSANDRA-11534 引起的。问题是这个(cql bug)是否与Java驱动问题有关。 Java 驱动程序文档的第 2 版提到了 MapCodec<K,V>。但是 3.1 的文档只有抽象版本 (AbstractMapCodec<K,V>)。 这实际上可能与编解码器无关。在小型数据集上,我的代码运行良好,但在大型数据集上却失败了。但它总是失败,有时在几秒钟内,有时在几十秒后。有时它也会因 AccessControlException on FilePermission" "C:\Program Files\DataStax-DDC\apache-cassandra\conf\logback.xml" "read" 而失败。 【参考方案1】:

这只是部分答案。对于大型数据集,我仍然经常在 Java 客户端和 cqlsh 中遇到 CodecNotFoundException。

我的部分问题是基于不正确的期望。我曾期望结果将作为行返回,每个地图条目都是一行。但查询结果是包含地图的单行。

读取结果的代码是:

Map<String,Double> map = queryResults.one().getMap( 0, String.class, Double.class);

【讨论】:

以上是关于Cassandra:带有地图结果的 UDF 在 Java 中获取 CodecNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

cassandra CQL 在 where 不使用 UDF

如何在 Spark Udf 中传递地图?

使用列名数组中的 UDF 将列合并到单个映射中

Pig into Cassandra - 使用 python UDF 和 CqlStorage 传递列表对象

在 Cassandra 中按地图值查询

在Cassandra中用新的键值对更新地图类型列,而不是完全覆盖地图。