如何按包含某些其他数据帧/集的任何值的数组列过滤Spark数据帧

Vas*_*kas 2 apache-spark apache-spark-sql spark-dataframe

我有一个包含一列数组字符串的Dataframe A.

...
 |-- browse: array (nullable = true)
 |    |-- element: string (containsNull = true)
...
Run Code Online (Sandbox Code Playgroud)

例如,三个样本行

+---------+--------+---------+
| column 1|  browse| column n|
+---------+--------+---------+
|     foo1| [X,Y,Z]|     bar1|
|     foo2|   [K,L]|     bar2|
|     foo3|     [M]|     bar3|
Run Code Online (Sandbox Code Playgroud)

另一个包含一列字符串的Dataframe B.

|-- browsenodeid: string (nullable = true)
Run Code Online (Sandbox Code Playgroud)

它的一些样本行

+------------+
|browsenodeid|
+------------+
|           A|
|           Z|
|           M|
Run Code Online (Sandbox Code Playgroud)

如何过滤A以便保留browse包含browsenodeidB 中任何值的所有行?就上述例子而言,结果将是:

+---------+--=-----+---------+
| column 1|  browse| column n|
+---------+--------+---------+
|     foo1| [X,Y,Z]|     bar1| <- because Z is a value of B.browsenodeid
|     foo3|     [M]|     bar3| <- because M is a value of B.browsenodeid
Run Code Online (Sandbox Code Playgroud)

如果我有一个值,那么我会使用类似的东西

A.filter(array_contains(A("browse"), single_value))
Run Code Online (Sandbox Code Playgroud)

但是我如何处理值列表或DataFrame呢?

Vas*_*kas 6

我找到了一个优雅的解决方案,无需将DataFrames/Datasets转换为RDDs.

假设您有一个DataFrame dataDF:

+---------+--------+---------+
| column 1|  browse| column n|
+---------+--------+---------+
|     foo1| [X,Y,Z]|     bar1|
|     foo2|   [K,L]|     bar2|
|     foo3|     [M]|     bar3|
Run Code Online (Sandbox Code Playgroud)

以及b包含要匹配的值的数组browse

val b: Array[String] = Array(M,Z)
Run Code Online (Sandbox Code Playgroud)

实现udf:

def array_contains_any(s: Seq[String]): UserDefinedFunction = udf((c: WrappedArray[String]) => c.toList.intersect(s).nonEmpty)
Run Code Online (Sandbox Code Playgroud)

然后简单地使用filterwhere函数(有点花哨的currying:P)进行过滤,如:

dataDF.where(array_contains_any(b)($"browse"))
Run Code Online (Sandbox Code Playgroud)