我正在使用Spark 2.3,并试图合并两个数据流。我的左右流都有一个数组。我只想在右流数组是左流数组的子集时加入两个流。
例如,我的streamA看起来像这样:
StreamA:
|---|------|---------------------|-----------|
|id | dept | employeesInMeetings | DateTime |
|---|------|---------------------|-----------|
| 1 | sales| [John] | 7/2 14:00 |
| 2 | mktg | [Adam, Mike] | 7/2 12:30 |
| 3 | hr | [Rick, Jill, Andy] | 7/2 14:00 |
|---|------|---------------------|-----------|
我的streamB看起来如下:
StreamB:
|--------------|--------------|----------|
|employees | confRooms | DateTime |
|--------------|--------------|----------|
| [John, Jane] | A | 7/2 14:00|
| [Adam, Mike] | C | 7/2 12:30|
| [Jill, Andy] | B | 7/2 14:00|
|--------------|--------------|----------|
我只关心同一个会议中来自同一部门的员工。因此,作为交集的结果,我产生的流需要看起来像:
|---|------|---------------------|-----------|----------|
|id | dept | employeesInMeetings | DateTime | confRoom |
|---|------|---------------------|-----------|----------|
| 2 | mktg | [Adam, Mike] | 7/2 12:30 | C |
| 3 | hr | [Rick, Jill, Andy] | 7/2 14:00 | B |
|---|------|---------------------|-----------|----------|
我创建了一个用于相交的UDF:
val arrayIntersect = udf((leftArr: Array[String], rightArr: Array[String]) => {
import spark.implicits._
if(leftArr.intersect(rightArr.toSeq).length == rightArr.size){
true
} else {
false
}
})
并尝试如下使用它:
streamA.joinWith(streamB, expr("arrayIntersect(leftArr, rightArr) AND streamA.DateTime BETWEEN streamB.DateTime and streamB.DateTime + INTERVAL 12 hours"))
但是,我得到了错误:
org.apache.spark.sql.AnalysisException: Stream stream joins without equality predicate is not supported;
有人知道这里是否有解决方法吗?任何帮助将不胜感激!谢谢!
答案 0 :(得分:1)
不幸的是,在流-流连接中没有解决方法:(
我们确实需要一个相等谓词,因为我们使用它来使用流对称哈希联接算法来执行联接-两个流都使用公共密钥进行分区,以便来自两个流的相关记录最终位于同一分区中。
答案 1 :(得分:-1)
首先将您的数组转换为字符串,然后在左侧的Array String中搜索右侧的Array String。
val arrayToString = udf{arr: Seq[String] => arr.sorted.map(_.trim.toLowerCase).mkString(",")}
streamA.withColumn("leftArrStr", arrayToString(col("leftArr"))).joinWith(
streamB.withColumn("rightArrStr", arrayToString(col("rightArr")))
, expr("instr(leftArrStr, rightArrStr) != 0 " +
"AND streamA.DateTime BETWEEN streamB.DateTime and streamB.DateTime + INTERVAL 12 hours"))