Spark с Scala: записывать нулевое значение поля в Cassandra вместо TupleValue

50
5

В одной из моих коллекций скажем, что у меня есть следующее поле:

f: frozen<tuple<text, set<text>>

Скажем, я хочу вставить запись, в которой это конкретное поле пустое, пустое, несуществующее и т.д., Используя скрипт Scala, где перед вставкой я сопоставляю поле ввода следующим образом:

sRow("fk") = null // or None, or maybe I simply don't specify the field at all

При попытке запустить искровой скрипт (из Databricks, Spark connector версии 1.6) я получаю следующую ошибку:

org.apache.spark.SparkException: Job aborted due to stage failure: Task 6 in stage 133.0 failed 1 times, most recent failure: Lost task 6.0 in stage 133.0 (TID 447, localhost): com.datastax.spark.connector.types.TypeConversionException: Cannot convert object null to com.datastax.spark.connector.TupleValue.
at com.datastax.spark.connector.types.TypeConverter$$anonfun$convert$1.apply(TypeConverter.scala:47)
at com.datastax.spark.connector.types.TypeConverter$$anonfun$convert$1.apply(TypeConverter.scala:43)

При использовании None вместо null я все равно получаю сообщение об ошибке, но другое:

org.apache.spark.SparkException: Job aborted due to stage failure: Task 2 in stage 143.0 failed 1 times, most recent failure: Lost task 2.0 in stage 143.0 (TID 474, localhost): java.lang.IllegalArgumentException: requirement failed: Expected 2 components, instead of 0
at scala.Predef$.require(Predef.scala:233)
at com.datastax.spark.connector.types.TupleType.newInstance(TupleType.scala:55)

Я понимаю, что у Cassandra нет точного понятия null, но я знаю, что есть способ оставить значения при вставке записей в Cassandra, поскольку я сделал это из других сред, например, используя драйвер nodejs для Cassandra. Как я могу принудительно присвоить значение null -like при вставке над ожидаемым TupleValue или, возможно, определенным пользователем типом?

спросил(а) 2016-12-27T17:06:00+03:00 3 года, 2 месяца назад
1
Решение
101

В современных версиях Cassandra вы можете использовать функцию "Unbound", чтобы она фактически пропускала нули. Это, вероятно, лучше всего подходит для вашего случая использования, потому что запись null неявно записывает надгробную плиту.

См. Раздел " Обработка нулей как сброс"

//Setup original data (1, 1, 1) --> (6, 6, 6)
sc.parallelize(1 to 6).map(x => (x, x, x)).saveToCassandra(ks, "tab1")

val ignoreNullsWriteConf = WriteConf.fromSparkConf(sc.getConf).copy(ignoreNulls = true)
//These writes will not delete because we are ignoring nulls
val optRdd = sc.parallelize(1 to 6)
.map(x => (x, None, None))
.saveToCassandra(ks, "tab1", writeConf = ignoreNullsWriteConf)

val results = sc.cassandraTable[(Int, Int, Int)](ks, "tab1").collect

results
/**
(1, 1, 1),
(2, 2, 2),
(3, 3, 3),
(4, 4, 4),
(5, 5, 5),
(6, 6, 6)
**/

Кроме того, есть много более мелкозернистого контроля. Полные документы

ответил(а) 2017-01-04T22:21:00+03:00 3 года, 1 месяц назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема