重命名后如何检查火花列的相等性

时间:2016-09-29 20:04:44

标签: java apache-spark apache-spark-sql

我正在尝试为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中修复了这也是很好的信息。)

谢谢你。

2 个答案:

答案 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.scalaAlias(及其child)未公开。它直接赋予ColumnwithExpr函数,该函数基于Alias命名表达式实例化新列。

因此,要么直接比较列上toString的结果(丢失列来自哪里的信息,即哪个数据帧),要么实际解析字符串打印 explain(true)方法......但这对我来说似乎不合理......