我正在尝试为Java Spark-Sql应用程序编写一些测试。我需要测试的一个操作重命名一个列,我遇到了一些困难,比较了重命名列的实际值和我的预期值。经过一些实验,我能够编写以下两个测试来证明问题:
首先,作为一个完整性检查,我尝试了这个(df是一个spark sql DataFrame
,通过读取我测试的json文件中的一些示例数据生成:
@Test
public void testColumnEquality() throws Exception {
Column val1 = df.col("col2");
Column val2 = df.col("col2");
Assert.assertEquals(val1, val2);
}
正如人们所预料的那样。然后我尝试了这个:
@Test
public void testReanmeColumnEquality() throws Exception {
Column val1 = df.col("col2").as("col2");
Column val2 = df.col("col2").as("col2");
Assert.assertEquals(val1, val2);
}
失败,错误为java.lang.AssertionError: expected:<col2 AS col2#4L> but was:<col2 AS col2#5L>
在scala代码中挖掘(完全披露 - 我知道很少scala),看起来这与NamedExpression
唯一ID有关。
有没有办法合理地检查这两列是否代表具有相同别名的相同操作?
(我在Spark 1.6中工作,理想情况下会喜欢该版本系列的解决方案,但如果在2.0中修复了这也是很好的信息。)
谢谢你。
答案 0 :(得分:2)
我写了关于如何解决这个问题的a blog post:
诀窍是:检查Expression
是否具有Alias
特征:
`column.expr() instanceof Alias`
如果是,请使用Extractor模式解压缩子表达式和名称:
alias = (Alias) column.expr()
Option<Tuple2<Expression, String>> aliasTuple = Alias$.MODULE$.unapply(alias);
答案 1 :(得分:0)
我做了一些挖掘,看起来在实例化新列的过程中,有关别名Column
的子项的信息丢失了。也许有一个状态可以在某处查询,但我没有找到它。
所以这不是一个答案,但希望它对某些人有用或感兴趣。
更多信息
as
对象上Column
方法的定义是指name
函数(请参阅https://my-storage.blob.core.windows.net/my-container/my-virtual-directory/image-name.png?sv=2015-12-11&sr=b&si=my-policy&sig=ZiKivSYXr63vBtdY7IsxVQ01WmrFnK%2FC9xABVrho6sY%3D&se=2016-10-04T15%3A37%3A11Z),它只调用Alias
案例类定义Column.scala。 Alias
(及其child
)未公开。它直接赋予Column
类withExpr
函数,该函数基于Alias
命名表达式实例化新列。
因此,要么直接比较列上toString
的结果(丢失列来自哪里的信息,即哪个数据帧),要么实际解析字符串打印 explain(true)
方法......但这对我来说似乎不合理......