Streaming 如何从Flink 1.2中的Kafka中提取json格式的部分字符串

Streaming 如何从Flink 1.2中的Kafka中提取json格式的部分字符串,streaming,apache-flink,Streaming,Apache Flink,我的目标是使用kafka读取json格式的字符串,对该字符串进行筛选,选择消息的一部分,并将消息以json字符串格式输出 出于测试目的,我的输入字符串消息如下所示: {"a":1,"b":2,"c":"3"} 我的实施守则是: def main(args: Array[String]): Unit = { val inputProperties = new Properties() inputProperties.setProperty("bootstrap.servers", "local

我的目标是使用kafka读取json格式的字符串,对该字符串进行筛选,选择消息的一部分,并将消息以json字符串格式输出

出于测试目的,我的输入字符串消息如下所示:

{"a":1,"b":2,"c":"3"}
我的实施守则是:

def main(args: Array[String]): Unit = {

val inputProperties = new Properties()
inputProperties.setProperty("bootstrap.servers", "localhost:9092")
inputProperties.setProperty("group.id", "myTest2")
val inputTopic = "test"

val outputProperties = new Properties()
outputProperties.setProperty("bootstrap.servers", "localhost:9092")
val outputTopic = "test2"


val env = StreamExecutionEnvironment.getExecutionEnvironment
env.getConfig.disableSysoutLogging
env.getConfig.setRestartStrategy(RestartStrategies.fixedDelayRestart(4, 10000))
// create a checkpoint every 5 seconds
env.enableCheckpointing(5000)

// create a Kafka streaming source consumer for Kafka 0.10.x
val kafkaConsumer = new FlinkKafkaConsumer010(
  inputTopic,
  new JSONDeserializationSchema(),
  inputProperties)

val messageStream : DataStream[ObjectNode]= env
  .addSource(kafkaConsumer).rebalance

val filteredStream: DataStream[ObjectNode] = messageStream.filter(node => node.get("a")
  .asText.equals("1") && node.get("b").asText.equals("2"))

// Need help in this part, how to extract for instance a,c and 
// get something like {"a":"1", "c":"3"}?
val testStream:DataStream[JsonNode] = filteredStream.map(
  node => {
    node.get("a")
  }
)

testStream.addSink(new FlinkKafkaProducer010[JsonNode](
  outputTopic,
  new SerializationSchema[JsonNode] {
    override def serialize(element: JsonNode): Array[Byte] = element.toString.getBytes()
  }, outputProperties
))

env.execute("Kafka 0.10 Example")
 }
正如这段代码的注释所示,我不知道如何正确地选择消息的一部分。我使用map,但我不知道如何连接整个消息。例如,我在代码中所做的只能给我一个结果1,但我想要的是{a:1,c:3}

或者也许有一种完全不同的方法来解决这个问题。事情是在火花流有一个选择的API,但我不能找到它在Flink


非常感谢flink社区的帮助!这是我想在这个小项目中实现的最后一个功能。

Flink Streaming job将每个输入处理一次,并将其输出到下一个任务或将其保存到外部存储器

一种方法是将所有输出保存到外部存储器中,如HDFS。流作业完成后,使用批处理作业将它们组合成JSON

另一种方法是使用state和RichMapFunction获取包含所有键值的JSON

stream.map(new MapFunction<String, Tuple2<String, String>>() {
    public Tuple2<String, String> map(String value) throws Exception {
        return new Tuple2<String, String>("mock", value);
    }
}).keyBy(0).map(new RichMapFunction<Tuple2<String,String>, String>() {
    @Override
    public String map(Tuple2<String, String> value) throws Exception {
        ValueState<String> old = getRuntimeContext().getState(new ValueStateDescriptor<String>("test", String.class));
        String newVal = old.value();
        if (newVal != null) makeJSON(newVal, value.f1);
        else newVal = value.f1;
        old.update(newVal);
        return newVal;
    }
}).print();
并使用此映射函数:filteredStream.mapfunction

请注意,使用状态时,您将看到如下输出: {a:1},{a:1,c:3}。
最后的输出应该是您想要的。

谢谢!makeJSON是Flink的内置函数吗?或者你的意思是我需要自己编写一个函数并把它放在那里?@teddy不,Flink不包括这样的方法,它是一个用于说明的伪代码。您可以实现一个。不需要很多代码;我得到一个错误,说Keyed state只能在“Keyed stream”上使用,即,在这行ValueState state=getRuntimeContext.getStatenew valuestatescriptorjson,String.class上的“keyBy”操作之后;我所做的是用{\a\:\+value.geta.toString+\,\c\:\+value.getc+}替换makeJSONstate.value和value。我不知道如何使用state.value变量,所以我只使用value并创建一个字符串json@DavidMy程序通过删除ValueState state=getRuntimeContext.getStatenew valuestatescriptorjson,string.class;和state.updatenewJSON;。但是我不确定这是不是一个好方法@David