【发布时间】:2016-04-22 09:07:18
【问题描述】:
使用 Spark 1.5 和 Scala 2.10.6
我正在尝试通过作为字符串数组的字段“标签”过滤数据框。查找所有带有“private”标签的行。
val report = df.select("*")
.where(df("tags").contains("private"))
得到:
线程“主”org.apache.spark.sql.AnalysisException 中的异常: 由于数据类型不匹配,无法解析“包含(标签,私有)”: 参数 1 需要字符串类型,但是,'tags' 是数组 类型。;
过滤方法是否更适合?
更新:
数据来自 cassandra 适配器,但显示我正在尝试做的事情并得到上述错误的最小示例是:
def testData (sc: SparkContext): DataFrame = {
val stringRDD = sc.parallelize(Seq("""
{ "name": "ed",
"tags": ["red", "private"]
}""",
"""{ "name": "fred",
"tags": ["public", "blue"]
}""")
)
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
import sqlContext.implicits._
sqlContext.read.json(stringRDD)
}
def run(sc: SparkContext) {
val df1 = testData(sc)
df1.show()
val report = df1.select("*")
.where(df1("tags").contains("private"))
report.show()
}
更新:标签数组可以是任意长度,“私有”标签可以在任意位置
更新:一种有效的解决方案:UDF
val filterPriv = udf {(tags: mutable.WrappedArray[String]) => tags.contains("private")}
val report = df1.filter(filterPriv(df1("tags")))
【问题讨论】:
-
发布您的数据样本以及您如何创建 df
-
一种选择是构建 UDF。
-
好吧,在查看源代码之后(因为
Column.contains的scaladoc 只说“包含其他元素”,这不是很有启发性),我看到Column.contains构造了一个@ 的实例987654326@ 表示“如果字符串left包含字符串right则返回 true 的函数”。因此,在这种情况下,df1("tags").contains似乎无法做我们希望它做的事情。我不知道有什么替代建议。在...expressions中也有一个ArrayContains,但Column似乎没有使用它。 -
确实,将数据改为字符串而不是字符串数组后,发现查询成功了。
-
@DavidMaust,我有一个 UDF 可以工作:
val filterPriv = udf {(tags: mutable.WrappedArray[String]) => tags.contains("private")}; val report = df1.filter(filterPriv(df1("tags")))仍在寻找更好的东西,但至少我没有被阻止。谢谢!
标签: scala apache-spark