我正在使用spark-core,spark-sql,Spark-hive 2.10(1.6.1),scala-reflect 2.11.2。我正在尝试过滤通过配置单元上下文创建的数据框...
df = hiveCtx.createDataFrame(someRDDRow,
someDF.schema());
我要过滤的一列中有多个单引号。我的过滤器查询将类似于
df = df.filter("not (someOtherColumn= 'someOtherValue' and comment= 'That's Dany's Reply'"));
在发生此过滤器的java类中,我尝试将String变量替换为例如commentValueToFilterOut,该变量包含
值“ That's Dany's Reply”commentValueToFilterOut= commentValueToFilterOut.replaceAll("'","\\\\'");
但是将过滤器应用于数据框时,出现以下错误...
java.lang.RuntimeException: [1.103] failure: ``)'' expected but identifier
s found
not (someOtherColumn= 'someOtherValue' and comment= 'That\'s Dany\'s Reply'' )
^
scala.sys.package$.error(package.scala:27)
org.apache.spark.sql.catalyst.SqlParser$.parseExpression(SqlParser.scala:49)
org.apache.spark.sql.DataFrame.filter(DataFrame.scala:768)
请告知...
答案 0 :(得分:0)
我们实施了一种解决方法来克服此问题。
解决方法:
在数据框中创建一个新列,然后将实际列中的值(其中包含特殊字符,可能会引起问题(如单引号))复制到不包含任何特殊字符的新列中。
df = df.withColumn("comment_new", functions.regexp_replace(df.col("comment"),"'",""));
修剪条件中的特殊字符并应用过滤器。
commentToFilter = "That's Dany's Reply'"
commentToFilter = commentToFilter.replaceAll("'","");
df = df.filter("(someOtherColumn= 'someOtherValue' and comment_new= '"+commentToFilter+"')");
现在,过滤器已应用,您可以删除仅为过滤目的创建的新列,并将其恢复到原始数据框。
df = df.drop("comment_new");
如果您不想在数据框中创建新列,也可以用同一列中的“永不发生”字符串文字替换特殊字符,例如
df = df.withColumn("comment", functions.regexp_replace(df.col("comment"),"'","^^^^"));
并对要应用的字符串文字进行相同操作
comment_new commentToFilter = "That's Dany's Reply'"
commentToFilter = commentToFilter.replaceAll("'","^^^^");
df = df.filter("(someOtherColumn= 'someOtherValue' and comment_new= '"+commentToFilter+"')");
一旦过滤完成,通过反向应用字符串litteral来恢复实际值
df = df.withColumn("comment", functions.regexp_replace(df.col("comment"),"^^^^", "'"));
尽管它不能解决实际问题,但是有相同问题的人可以尝试解决此问题。
实际的解决方案可能是使用sqlContext(而不是hiveContext)和/或Dataset(而不是dataframe)和/或升级到spark hive 2.12。
辩论和回答专家
PS:多亏了我的领导KP