我们有一个用例,其中我们正在接收来自kafka的消息,需要对其进行汇总。必须采用以下方式进行汇总:如果更新的ID相同,则需要减去现有值并添加新值。
从各种论坛上,我了解到jet不会存储原始值,而是存储汇总结果和一些内部数据。
在这种情况下,我该如何实现?
示例
Balance 1 {id:1, amount:100} // aggregated result 100
Balance 2 {id:2, amount:200} // 300
Balance 3 {id:1, amount:400} // 600 after removing 100 and adding 400
我可以实现每次添加的简单用法。但是我无法实现需要减去现有值并必须添加新值的汇总。
rollingAggregation(AggregatorOperations.summingDouble(<login to add remove>))
.drainTo(Sinks.logger()).
答案 0 :(得分:1)
您可以尝试执行自定义聚合操作,该操作将发出以前和当前看到的值,如下所示:
public static <T> AggregateOperation1<T, ?, Tuple2<T, T>> previousAndCurrent() {
return AggregateOperation
.withCreate(() -> new Object[2])
.<T>andAccumulate((acc, current) -> {
acc[0] = acc[1];
acc[1] = current;
})
.andExportFinish((acc) -> tuple2((T) acc[0], (T) acc[1]));
}
输出应为(previous, current)
形式的元组。然后,您可以将滚动聚合再次应用于输出。为了简化输入问题,我有一对(id, amount)
对。
Pipeline p = Pipeline.create();
p.drawFrom(Sources.<Integer, Long>mapJournal("map", START_FROM_OLDEST)) // (id, amount)
.groupingKey(Entry::getKey)
.rollingAggregate(previousAndCurrent(), (key, val) -> val)
.rollingAggregate(AggregateOperations.summingLong(e -> {
long prevValue = e.f0() == null ? 0 : e.f0().getValue();
long newValue = e.f1().getValue();
return newValue - prevValue;
}))
.drainTo(Sinks.logger());
JetConfig config = new JetConfig();
config.getHazelcastConfig().addEventJournalConfig(new EventJournalConfig().setMapName("map"));
JetInstance jet = Jet.newJetInstance(config);
IMapJet<Object, Object> map = jet.getMap("map");
map.put(0, 1L);
map.put(0, 2L);
map.put(1, 10L);
map.put(1, 40L);
jet.newJob(p).join();
这应该产生为输出:1, 2, 12, 42
。