Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spark SQL-如何从历元中选择存储为UTC毫秒的日期?_Sql_Date_Apache Spark_Apache Spark Sql - Fatal编程技术网

Spark SQL-如何从历元中选择存储为UTC毫秒的日期?

Spark SQL-如何从历元中选择存储为UTC毫秒的日期?,sql,date,apache-spark,apache-spark-sql,Sql,Date,Apache Spark,Apache Spark Sql,我一直在搜索,但还没有找到一个解决方案,即如何使用Spark SQL查询以UTC毫秒形式存储的日期。我从MongoDB的NoSQL数据源JSON中提取的模式的目标日期为: |-- dateCreated: struct (nullable = true) ||-- $date: long (nullable = true) 完整的模式如下所示: scala> accEvt.printSchema root |-- _id: struct (nullable = true) |

我一直在搜索,但还没有找到一个解决方案,即如何使用Spark SQL查询以UTC毫秒形式存储的日期。我从MongoDB的NoSQL数据源JSON中提取的模式的目标日期为:

|-- dateCreated: struct (nullable = true)

||-- $date: long (nullable = true)
完整的模式如下所示:

scala> accEvt.printSchema
root
 |-- _id: struct (nullable = true)
 |    |-- $oid: string (nullable = true)
 |-- appId: integer (nullable = true)
 |-- cId: long (nullable = true)
 |-- data: struct (nullable = true)
 |    |-- expires: struct (nullable = true)
 |    |    |-- $date: long (nullable = true)
 |    |-- metadata: struct (nullable = true)
 |    |    |-- another key: string (nullable = true)
 |    |    |-- class: string (nullable = true)
 |    |    |-- field: string (nullable = true)
 |    |    |-- flavors: string (nullable = true)
 |    |    |-- foo: string (nullable = true)
 |    |    |-- location1: string (nullable = true)
 |    |    |-- location2: string (nullable = true)
 |    |    |-- test: string (nullable = true)
 |    |    |-- testKey: string (nullable = true)
 |    |    |-- testKey2: string (nullable = true)
 |-- dateCreated: struct (nullable = true)
 |    |-- $date: long (nullable = true)
 |-- id: integer (nullable = true)
 |-- originationDate: struct (nullable = true)
 |    |-- $date: long (nullable = true)
 |-- processedDate: struct (nullable = true)
 |    |-- $date: long (nullable = true)
 |-- receivedDate: struct (nullable = true)
 |    |-- $date: long (nullable = true)
我的目标是按照以下思路编写查询:

SELECT COUNT(*) FROM myTable WHERE dateCreated BETWEEN [dateStoredAsLong0] AND [dateStoredAsLong1]
迄今为止,我的过程是:

scala> val sqlContext = new org.apache.spark.sql.SQLContext(sc)
sqlContext: org.apache.spark.sql.SQLContext = org.apache.spark.sql.SQLContext@29200d25

scala> val accEvt = sqlContext.jsonFile("/home/bkarels/mongoexport/accomplishment_event.json")

...
14/10/29 15:03:38 INFO SparkContext: Job finished: reduce at JsonRDD.scala:46, took 4.668981083 s
accEvt: org.apache.spark.sql.SchemaRDD = 
SchemaRDD[6] at RDD at SchemaRDD.scala:103

scala> accEvt.registerAsTable("accomplishmentEvent")
此时,以下基线查询将成功执行

现在,我无法正确理解的巫毒是如何形成我的select语句来解释日期。例如,下面的代码执行w/o error,但返回零,而不是所有记录的计数,因为它应该返回74475

scala> sqlContext.sql("select count(*) from accomplishmentEvent where processedDate >= '1970-01-01'").collect.foreach(println)
...
[0]
我也尝试过一些丑陋的东西,比如:

scala> val now = new java.util.Date()
now: java.util.Date = Wed Oct 29 15:05:15 CDT 2014

scala> val today = now.getTime
today: Long = 1414613115743

scala> val thirtydaysago = today - (30 * 24 * 60 * 60 * 1000)
thirtydaysago: Long = 1416316083039


scala> sqlContext.sql("select count(*) from accomplishmentEvent where processedDate <= %s and processedDate >= %s".format(today,thirtydaysago)).collect.foreach(println)
返回:

[[1376318850033]]
[[1376319429590]]
[[1376320804289]]
[[1376320832835]]
[[1376320832960]]
[[1376320835554]]
[[1376320914480]]
[[1376321041899]]
[[1376321109341]]
[[1376321121469]]
然后扩展到我尝试过的日期:

scala> sqlContext.sql("select cId from accomplishmentEvent where receivedDate.date > '1970-01-01' limit 5").collect.foreach(println)
导致错误的原因:

java.lang.RuntimeException: No such field date in StructType(ArrayBuffer(StructField($date,LongType,true)))
...
在字段名前面加上$as也会导致另一种错误:

scala> sqlContext.sql("select cId from accomplishmentEvent where receivedDate.$date > '1970-01-01' limit 5").collect.foreach(println)
java.lang.RuntimeException: [1.69] failure: ``UNION'' expected but ErrorToken(illegal character) found

select actualConsumerId from accomplishmentEvent where receivedDate.$date > '1970-01-01' limit 5
显然,我不知道如何选择以这种方式存储的日期-有人能帮我填补这个空白吗

我对Scala和Spark都比较新,所以如果这是一个基本问题,请原谅我,但是我的搜索结果在论坛和Spark文档中都是空的


谢谢。

您的JSON不是扁平的,因此顶级下面的字段需要使用限定名称(如dateCreated.$date)进行寻址。您的特定日期字段都是长类型的,因此您需要对它们进行数字比较,看起来您在正确的轨道上进行了比较

另一个问题是,字段名有$个字符,Spark SQL不允许您查询它们。一种解决方案是,先将JSON作为RDD[String]读取,然后使用map方法执行您选择的Scala字符串操作,然后使用SQLContext的jsonRDD方法创建SchemaRDD,而不是像之前那样直接将JSON作为SchemaRDD读取

我已经用Spark 1.1.0测试过了


作为参考,Spark SQL中缺少引用功能的问题已在和其他文章中提到,而且似乎是最近才修复的,但要将其发布到一个版本中还需要一些时间

请澄清您在哪方面遇到了问题?它是否构造了正确的筛选表达式,即:查询中的WHERE子句?另外,你大概已经知道了如何将数据放入RDD中:RDD的类型是什么?我在我的帖子中添加了更多的细节,更准确地概述了我所做的事情以及逃避我的是什么。谢谢。有两件事需要尝试:1将accEvt.printSchema的完整输出添加到您的问题中,或者顶部的片段实际上就是全部内容吗?和2尝试选择一个或多个特定字段,而不是*来检查字段命名是否有效。看起来您的JSON不是平面的,所以我想知道您的代码片段中显示的字段是否需要作为dataCreated.$data进行寻址-我注意到Spark SQL文档中的JSON示例是平面的。我已经验证了在Spark 1.1.0中,点表示法可以用于访问嵌套字段。但是,您的下一个问题是,您的字段名中有一个$,并且dateCreated.$date不是有效的Spark SQL标识符。它似乎与那些真正应该写出来说更一般的东西有关。通常的SQL方括号引号也不起作用。Spark SQL解析器非常原始,很可能很快就会被重写。也许你可以处理RDD以去除美元符号,或者预处理文件。刚刚注意到你最近的编辑。注意你的receivedDate是如何用两个方括号打印出来的吗?这就是筑巢行动!因此,出于某种原因,原始JSON中的mongo导出将my date对象转换为嵌套的$date字段名。因此,我测试了您的想法并转换了“$date”->“date”,然后我可以使用长值进行查询,例如选择processedDate.date。我仍然需要将日期转换为毫秒,并将它们注入到查询中,以执行范围之类的操作,但我想这就是以这种方式存储日期所付出的代价。我现在必须研究mongo export正在做什么,并将其纳入我们的未来战略。谢谢你的帮助!需要记住的是,您可以在传递数据的过程中进行其他翻译。将epoch毫秒转换为其他Scala日期格式在这个站点上的问答中包含大量信息是非常容易的。问题是,您需要弄清楚Spark SQL实际上可以处理哪种类型的日期比较,我还没有研究过。OTOH,如果Spark SQL不能[目前]处理您想要的内容,那么使用straight Spark过滤RDD也是非常直接的。
java.lang.RuntimeException: No such field date in StructType(ArrayBuffer(StructField($date,LongType,true)))
...
scala> sqlContext.sql("select cId from accomplishmentEvent where receivedDate.$date > '1970-01-01' limit 5").collect.foreach(println)
java.lang.RuntimeException: [1.69] failure: ``UNION'' expected but ErrorToken(illegal character) found

select actualConsumerId from accomplishmentEvent where receivedDate.$date > '1970-01-01' limit 5
val lines = sc.textFile(...)
// you may want something less naive than global replacement of all "$" chars
val linesFixed = lines.map(s => s.replaceAllLiterally("$", ""))
val accEvt = sqlContext.jsonRDD(linesFixed)