【问题标题】:Concatenate timestamp column with string column将时间戳列与字符串列连接起来
【发布时间】:2019-01-28 14:28:40
【问题描述】:

我需要将数据从 Cassandra 推送到 Elasticsearch。从cassandra 加载数据帧,但名为timestamp 的列是Long 格式,所以我需要将其更改为timestamp 以更“人类可读”,我这样做了:

val cassDF2 = spark.createDataFrame(rawCass).withColumn("timestamp", ($"timestamp").cast(TimestampType))

数据框现在看起来像:

+--------------------+--------------------+-------------+--------------------+--------------------+
|             eventID|           timestamp|       userID|           sessionID|            fullJson|
+--------------------+--------------------+-------------+--------------------+--------------------+
|event00001.withSa...| 2018-11-15 09:00...|2512988381908|  WITH_EVENTS_IMPORT|{"header": {"appI...|
|event00002.withSa...| 2018-11-15 09:00...|2512988381908|WITH_EVENTS_SESSI...|{"body": {}, "hea...|
|event00003.withPa...| 2018-11-15 09:00...|2006052984315|  WITH_EVENTS_IMPORT|{"header": {"appI...|
+--------------------+--------------------+-------------+--------------------+--------------------+

现在,我需要将 3 列 (seesionID, userID and timestamp) 连接成一个新列 (docID) 并将其推送到 ES:

  // concatStrings function
  val concatStrings = udf((userID: String, timestamp: String, eventID: String) => {userID + timestamp + eventID})

  // create column docID
  val cassDF = cassDF2.withColumn("docID", concatStrings($"userID", $"timestamp", $"eventID"))

得到错误:

org.apache.spark.sql.AnalysisException:“时间戳”不是数字 柱子。聚合函数只能应用于数值列。

我知道timestamp 在调用.cast 之后现在是一个对象并且不能像以前那样聚合(当它是Long 类型时),但是如何将它的值提取为字符串或可以聚合的东西。

我所能得到的就是在timestamp 列是Long 时完成此操作。

我的最终数据框应该看起来像 cassDF2,但新列 docID 包含 251929883819082018-12-09T12:25:25.904+0100event00001.withSa... 而不是 docID 中的 15147612000002512988381908event00001.withSa...

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    不需要UDF。您可以使用内置方法concat 将包括具有特定日期格式的字符串格式timestamp 列在内的列拼凑在一起,如下所示:

    import spark.implicits._
    import org.apache.spark.sql.functions._
    import java.sql.Timestamp
    
    val df = Seq(
      ("1001", Timestamp.valueOf("2018-11-15 09:00:00"), "Event1"),
      ("1002", Timestamp.valueOf("2018-11-16 10:30:00"), "Event2")
    ).toDF("userID", "timestamp", "eventID")
    
    val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    
    df.
      withColumn("docID", concat($"userID", date_format($"timestamp", dateFormat), $"eventID")).
      show(false)
    // +------+-------------------+-------+--------------------------------------+
    // |userID|timestamp          |eventID|docID                                 |
    // +------+-------------------+-------+--------------------------------------+
    // |1001  |2018-11-15 09:00:00|Event1 |10012018-11-15T09:00:00.000-0800Event1|
    // |1002  |2018-11-16 10:30:00|Event2 |10022018-11-16T10:30:00.000-0800Event2|
    // +------+-------------------+-------+--------------------------------------+
    

    【讨论】:

    • 导入后Cassandra中的文档数量与ES中的数量不相等,即使我的脚本正在处理相同数量的文档,是否有任何原因?
    • @Dejan Marić,而不是作为评论发布,我建议您使用相关标签(例如 Cassandra/Elasticsearch)和可以重现上述问题的最小数据集组合一个单独的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 2022-08-04
    • 1970-01-01
    相关资源
    最近更新 更多