【问题标题】:How to remove chars from alphanumeric values in cassandra column?如何从 cassandra 列中的字母数字值中删除字符?
【发布时间】:2019-12-28 12:33:09
【问题描述】:

我有如下所示的数据模型。我的问题是在 ma​​rks 列中而不是 int 值中插入了字母数字值,因此需要通过从 ma​​rks 中的每个字母数字值中删除字符来清理此列> 专栏

我想通过编程来做到这一点,所以想继续使用 apache spark、scala 来编写一个 spark 作业并针对 cassandra 运行。我对这两种技术都是新手,所以任何人都可以让我知道 spark 中是否有任何内置功能可以做到这一点,或者我可以采取的任何最佳方法。感谢您的建议。

我知道我可以使用 spark 数据帧,但对如何在数据帧上编写 scala reg 表达式来执行此操作并坚持回来感到困惑。

CREATE TABLE student (
    student_id text,
    dob text,
    subject text,
    marks text,
    PRIMARY KEY (student_id, dob, subject, marks)
) WITH CLUSTERING ORDER BY (dob DESC, subject ASC, marks ASC).

现在在我的student 表中,标记列应该存储 int 值,但由于一些错误的工作,所以插入了许多带有 alpha-numeric 值的记录,如下所示:

===============================================
student_id |  dob         |  subject  |  marks
===============================================
1          | 10-05-2019   | A         | ab50
2          | 08-06-2019   | B         | 88
3          | 02-02-2019   | C         | h65u
4          | 04-02-2019   | D         | 99

现在我想清理这个表,从存储在标记列中的字母数字值中删除所有字符。

例如:ab50 -> 50(这是预期结果)。

【问题讨论】:

标签: scala apache-spark cassandra


【解决方案1】:

这个特殊的用例可以使用 UDF 来解决。示例代码如下:

import org.apache.spark.sql.functions.udf
import spark.implicits._

val cleanUDF = udf((x: String) => x.filter(_.toString.matches("\\d")))

val rows = List(
  (1, "10-05-2019", "A", "ab50"),
  (2, "08-06-2019", "B", "88"),
  (3, "02-02-2019", "C", "h65u"),
  (4, "04-02-2019", "D", "99")
)
val inDF = spark.sparkContext.parallelize(rows).toDF("student_id", "dob", "subject", "marks")
inDF.show()
//  +----------+----------+-------+-----+
//  |student_id|       dob|subject|marks|
//  +----------+----------+-------+-----+
//  |         1|10-05-2019|      A| ab50|
//  |         2|08-06-2019|      B|   88|
//  |         3|02-02-2019|      C| h65u|
//  |         4|04-02-2019|      D|   99|
//  +----------+----------+-------+-----+

//inDF using data from cassandra db
/*val inDF = spark.read
  .format("org.apache.spark.sql.cassandra")
  .options(Map("table" -> "student", "keyspace" -> "$keyspace"))
  .load()
*/

val outDF = inDF.select(
  $"student_id", $"dob", $"subject", cleanUDF($"marks").alias("marks")
)
outDF.show()
//  +----------+----------+-------+-----+
//  |student_id|       dob|subject|marks|
//  +----------+----------+-------+-----+
//  |         1|10-05-2019|      A|   50|
//  |         2|08-06-2019|      B|   88|
//  |         3|02-02-2019|      C|   65|
//  |         4|04-02-2019|      D|   99|
//  +----------+----------+-------+-----+

-----编辑---- 可以在 cassandra 中覆盖数据,以避免由于主键约束而导致重复条目。 免责声明:输出 DF 必须包含整个数据,因为它将被截断和加载。

outDF.write.format("org.apache.spark.sql.cassandra")
.options(Map(
  "keyspace" -> "$keyspace",
  "table" -> "student",
  "confirm.truncate" -> "true"
))
.mode(SaveMode.Overwrite).save()

【讨论】:

  • 非常感谢您的回复,这里我遇到了一个问题,当我将数据持久化回 Cassandra 时,新行正在创建而不是更新,因为 marks 列也是一部分主键 所以你能告诉我如何更新 Cassandra 中的数据框行吗?
  • 你不能从行键列中删除 marks 列吗?理想情况下,如果我们将其与现实世界的场景进行比较,标记不应该是唯一列的一部分。如果您确实需要主键中的 marks 列,那么在写入数据时您可以指定不同的表名。成功写入完成后,您可以删除以前的表并用旧表重命名新表。
  • 我理解你的意思,这里我采取的学生示例是虚拟的,但我的真实表结构是相同的,只有表名和列名不同。只是为了名字的缘故,我已经将该列作为标记。你能帮我考虑到标记是主键的一部分,我怎样才能将它更新回 Cassandra
  • @JagadeeshNM 我已经编辑了我的答案,以便在 cassandra 中为 主键 用例提供更好的编写解决方案。您可以简单地覆盖表格。
  • 好的@pritesh 我会试试那个,我相信你的解决方案不会截断学生表中的整个数据,它应该只覆盖更新的行。如果你看上面的例子 student_id 1 和 3 只需要清理其余的学生都很好,所以我会尝试,我会告诉你。非常感谢您的回答。
【解决方案2】:

可以使用自定义 udf 并在 cassandra 中更新

【讨论】:

    猜你喜欢
    • 2022-09-23
    • 2012-11-15
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多