我需要实现类似的目标:
Checking if values in List is part of String
在火花中。也就是说,有一个数据框架:
abcd_some long strings
goo bar baz
以及一系列想要的单词,比如
["some", "bar"]
.
使用此代码的UDF可以很好地工作,但是,我希望有更有效的方法。有没有办法表达
FILTER my_col CONTAINS ONE OF [items]
使用SQL DSL?也许通过动态构造regex?
注意:它不是一个exat匹配,而是一个常规的“contains”(包含)/如“%thing%”。也就是说,不完全匹配。否则
isIn
接线员会工作的。
编辑
可能动态生成一些SQL代码是最有效的方法。
def orFilterGeneratorMultiContains(filterPredicates:Seq[String], column:String):Column = {
col(column).contains(filterPredicates(0)) or col(column).contains(filterPredicates(1)) // TODO iterate
}
def filterToDesiredApps(filterPredicates:Seq[String], column:String)(df:DataFrame):DataFrame={
df.filter(orFilterGeneratorMultiContains(filterPredicates, column))
}
所以仍然需要弄清楚如何正确地迭代表达式。
编辑2
然而,这有点棘手:
import org.apache.spark.sql.functions.col
val column = col("foo")
val interstingTHings = Seq("bar", "baz", "thing3")
interstingTHings.foldLeft(column) { (filteredOrColumnExpression, predicateItem) =>
// TODO how to properly nest the OR operator?
// filteredOrColumnExpression.contains(predicateItem) // generates: Contains(Contains(Contains('foo, bar), baz), thing3)
filteredOrColumnExpression or filteredOrColumnExpression.contains(predicateItem) // generates: ((('foo || Contains('foo, bar)) || Contains(('foo || Contains('foo, bar)), baz)) || Contains((('foo || Contains('foo, bar)) || Contains(('foo || Contains('foo, bar)), baz)), thing3))
// TODO but what y really would need is:
// col(column).contains("bar") or col(column).contains("baz") or col(column).contains("thing3")
}.explain(true)
因为它不能产生正确的
OR
嵌套的筛选条件。