【发布时间】:2020-09-07 08:25:23
【问题描述】:
我正在尝试将 WindowFunction 与 DataStream 一起使用,我的目标是有一个如下所示的查询
SELECT *,
count(id) OVER(PARTITION BY country) AS c_country,
count(id) OVER(PARTITION BY city) AS c_city,
count(id) OVER(PARTITION BY city) AS c_addrs
FROM fm
ORDER BY country
已经帮助我按国家字段进行聚合,但我需要在同一时间窗口中按两个字段进行聚合。 对于这种情况,我不知道 keyBy( ) 中是否可以有两个或多个键
val parsed = stream2.map(x=> {
val arr = x.split(",")
(arr(0).toInt, arr(1), arr(2))
})
parsed
.keyBy(x => x._2)
.window(TumblingProcessingTimeWindows.of(Time.seconds(60)))
.process(new ProcessWindowFunction[
(Int, String, String), (Int, String, String, Int), String, TimeWindow
]() {
override def process(key: String, context: Context,
elements: Iterable[(Int, String, String)],
out: Collector[(Int, String, String, Int)]): Unit = {
val lst = elements.toList
lst.foreach(x => out.collect((x._1, x._2, x._3, lst.size)))
}
}).print().setParallelism(1)
这对于第一次聚合非常有用,但我错过了同一时间窗口中城市字段的第二次聚合。
输入数据:
10,"SPAIN","BARCELONA","C1"
20,"SPAIN","BARCELONA","C2"
30,"SPAIN","MADRID","C3"
30,"SPAIN","MADRID","C3"
80,"SPAIN","MADRID","C4"
90,"SPAIN","VALENCIA","C5"
40,"ITALY","ROMA","C6"
41,"ITALY","ROMA","C7"
42,"ITALY","VENECIA","C8"
50,"FRANCE","PARIS","C9"
60,"FRANCE","PARIS","C9"
70,"FRANCE","MARSELLA","C10"
预期输出
(10,"SPAIN","BARCELONA",6,2,1)
(20,"SPAIN","BARCELONA",6,2,1)
(30,"SPAIN","MADRID",6,3,2)
(30,"SPAIN","MADRID",6,3,2)
(80,"SPAIN","MADRID",6,3,1)
(90,"SPAIN","VALENCIA",6,1,1)
(50,"FRANCE","PARIS",3,2,1)
(60,"FRANCE","PARIS",3,2,1)
(70,"FRANCE","MARSELLA",3,1,1)
(40,"ITALY","ROMA",3,2,2)
(41,"ITALY","ROMA",3,2,2)
(42,"ITALY","VENECIA",3,1,1)
---------------- 更新 2 ------------------
我目前想对 3 列进行聚合。如果我使用的选项是链接 KeyBy() 输出,但这可能会变得非常长和复杂,而且可读性不强。 除此之外,我放了一个 Time.seconds(1) 的时间窗口,因为没有这个窗口,上面的 KeyBy() 输出将作为单独的事件。
我的兴趣是我是否可以在单个进程函数中进行这些聚合。
我有这么长的代码...
parsed
.keyBy(_.country) // key by product id.
.window(TumblingProcessingTimeWindows.of(Time.seconds(60)))
.process(new ProcessWindowFunction[
AlarmasIn, AlarmasOut, String, TimeWindow
]() {
override def process(key: String, context: Context,
elements: Iterable[AlarmasIn],
out: Collector[AlarmasOut]): Unit = {
val lst = elements.toList
lst.foreach(x => out.collect(AlarmasOut(x.id, x.country, x.city,x.address, lst.size,0,0)))
}
})
.keyBy( _.city).window(TumblingProcessingTimeWindows.of(Time.seconds(1)))
.process(new ProcessWindowFunction[
AlarmasOut, AlarmasOut, String, TimeWindow
]() {
override def process(key: String,
context: Context,
elements: Iterable[AlarmasOut],
out: Collector[AlarmasOut]): Unit = {
val lst = elements.toList
lst.foreach(x => out.collect(AlarmasOut(x.id, x.country, x.city,x.address,x.c_country,lst.size,x.c_addr)))
}
})
.keyBy( _.address).window(TumblingProcessingTimeWindows.of(Time.seconds(1)))
.process(new ProcessWindowFunction[
AlarmasOut, AlarmasOut, String, TimeWindow
]() {
override def process(key: String,
context: Context,
elements: Iterable[AlarmasOut],
out: Collector[AlarmasOut]): Unit = {
val lst = elements.toList
lst.foreach(x => out.collect(AlarmasOut(x.id, x.country, x.city,x.address,x.c_country,x.c_city,lst.size)))
}
})
.print()
/// CASE CLASS
case class AlarmasIn(
id: Int,
country: String,
city: String,
address: String
)
case class AlarmasOut(
id: Int,
country: String,
city: String,
address: String,
c_country: Int,
c_city: Int,
c_addr: Int
)
【问题讨论】:
标签: scala stream apache-flink flink-streaming