Java 使用DataStax Spark连接器在Cassandra中保存空值
我尝试使用Spark和Cassandra Spark连接器将流数据保存到Cassandra中 我做了如下的事情: 创建模型类:Java 使用DataStax Spark连接器在Cassandra中保存空值,java,cassandra,apache-spark,Java,Cassandra,Apache Spark,我尝试使用Spark和Cassandra Spark连接器将流数据保存到Cassandra中 我做了如下的事情: 创建模型类: public class ContentModel { String id; String available_at; //may be null public ContentModel(String id, String available_at){ this.id=id; this.available_at=availab
public class ContentModel {
String id;
String available_at; //may be null
public ContentModel(String id, String available_at){
this.id=id;
this.available_at=available_at,
}
}
将流媒体内容映射到模型:
JavaDStream<ContentModel> contentsToModel = myStream.map(new Function<String, ContentModel>() {
@Override
public ContentModel call(String content) throws Exception {
String[] parts = content.split(",");
return new ContentModel(parts[0], parts[1]);
}
});
如果某些值为null
I,则会出现以下错误:
com.datastax.spark.connector.types.TypeConversionException: Cannot convert object null to struct.ValueRepr.
有没有办法使用Spark Cassandra连接器存储空值?Cassandra没有空值的概念。列为空或已填充。我在scala中通过以下方式解决了这个问题:我使用map方法并检查空值。我用空字符串覆盖null。就这样。工作非常好。在scala中,您也可以为此使用选项。我们可以知道您的依赖项(Spark、Connector、Cassandra等)的版本吗 是的,有一种方法可以使用Cassandra连接器存储空值。我让您的示例通过一个简单的应用程序和一些更改(添加Serializabe+将您的模型属性转换为Camel-Case+相对的getter和setter)正常工作。我对JavaAPI不太熟悉(在执行Spark时,您真的应该使用Scala,它使事情变得更简单),但我的印象是,对模型类的反射是在getter/setter级别完成的。。。可能是错的 模型
public class ModelClass implements Serializable {
String id;
String availableAt; //may be null
public ModelClass(String id, String availableAt){
this.id=id;
this.availableAt=availableAt;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAvailableAt() {
return availableAt;
}
public void setAvailableAt(String availableAt) {
this.availableAt = availableAt;
}
}
司机
public static void main(String ... args) {
SparkConf conf = new SparkConf();
conf.setAppName("Local App");
conf.setMaster("local[*]");
JavaSparkContext context = new JavaSparkContext(conf);
List<ModelClass> modelList = new ArrayList<>();
modelList.add(new ModelClass("Test", null));
modelList.add(new ModelClass("Test2", "test"));
context.parallelize(modelList);
JavaRDD<ModelClass> modelRDD = context.parallelize(modelList);
javaFunctions(modelRDD).writerBuilder("test", "model", mapToRow(ModelClass.class))
.saveToCassandra();
}
不过,了解如何“写入”空值的含义很重要。一般来说,我们希望避免写空,因为Cassandra是如何生成墓碑的。如果这些是初始写入,您将希望将它们视为“未设置” 全局将所有空值视为未设置 全局地将所有空值视为未设置的WriteConf现在还包含 可通过使用SparkConf键设置的参数ignoreNulls spark.cassandra.output.ignoreNulls。默认值为false,这将 使空值与以前的版本一样处理(插入到 卡桑德拉(原样)。当设置为true时,所有空值都将被视为未设置。 这可以与数据帧一起使用,以跳过空记录并避免 墓碑
编辑:我应该澄清一下,在内部,Cassandra没有存储实际的空值-它只是未设置。但是我们可以用Cassandra在应用程序级别使用null进行推理。提供同样的更多细节,我不这么认为。我已经尝试使用Datastax的java映射驱动程序将空值插入Cassandra表,并且成功了,即使列类型是int和float。Cassandra也显示null并返回null,因此“Cassandra没有null的概念”这句话就不太令人信服了。遇到这个错误:java.lang.NoSuchMethodError:org.apache.SparkContext.getExecutorStorageStatus()[Lorg/apache/spark/storage/StorageStatus;在com.datastax.spark.connector.cql.CassandraConnector$.apply(CassandraConnector.scala:204)位于com.datastax.spark.connector.RDDFunctions.saveToCassandra$default$5(RDDFunctions.scala:32)…53 elidedSpark版本:2.4。3@SumitAgarwal当您的spark连接器版本与您的spark版本不兼容时,您会发现这是一个例外。您可以检查兼容性矩阵:谢谢您的帮助,如果可能的话,您可以查看一下吗:
public static void main(String ... args) {
SparkConf conf = new SparkConf();
conf.setAppName("Local App");
conf.setMaster("local[*]");
JavaSparkContext context = new JavaSparkContext(conf);
List<ModelClass> modelList = new ArrayList<>();
modelList.add(new ModelClass("Test", null));
modelList.add(new ModelClass("Test2", "test"));
context.parallelize(modelList);
JavaRDD<ModelClass> modelRDD = context.parallelize(modelList);
javaFunctions(modelRDD).writerBuilder("test", "model", mapToRow(ModelClass.class))
.saveToCassandra();
}
cqlsh:test> select * from model;
id | available_at
-------+--------------
Test | null
Test2 | test