Kafka流返回所有记录,其中fieldx =某个值

时间:2019-07-03 15:29:41

标签: java apache-kafka-streams spring-kafka

我有多个非唯一字段进入卡夫卡的记录,我们称它们为Field1 ... Field n。

我想编写一个查询以返回其中fieldx =某个值的所有记录。让我们举一个简单的例子。假设订单进入系统,订单中的一个字段是customerId。基本操作是获取特定客户的所有订单。如何使用Kafka Streams做到这一点?

我已经有了一个KTable和所有记录的实例化视图,因此我可以遍历视图中的所有记录并挑选出我想要的记录,但这似乎效率低下且成本高昂。 / p>

我真的很想创建一个物化视图,其中该视图包含由fieldx分组的记录,但是我看不到任何实现此目的的方法。看来您只能在汇总,计数,减少等情况下使用groupby。

关于如何执行此操作的任何想法?

2 个答案:

答案 0 :(得分:1)

这里是一个按客户ID过滤订单的示例。对于此查询,无需创建用于分组或聚合的KTable。然而,由于Kafka主题是不带二级索引的仅追加日志,因此您确实需要遍历所有消息以查找与您的客户ID匹配的订单流。

StreamsBuilder builder = new StreamsBuilder();
KStream<String, Order> orderStream = builder.stream("orders");
orderStream.filter((k,v) -> "customer-1".equals(v.customerId));

请注意,以上代码假定您的订单流中也具有String类型的键,但是这些键将被忽略。

还要注意,您将需要指定Kafka Streams如何将消息反序列化到Order类中。您可以使用Consumed.with(...)指定反序列化器。

有关完整示例,请参见github上的Kafka Streams示例存储库:https://github.com/confluentinc/kafka-streams-examples

并不是说也可以使用KSQL编写这些类型的查询:https://www.confluent.io/stream-processing-cookbook/

答案 1 :(得分:0)

您应在“ customerID”上对订单流进行分组,并将所有订单汇总到一个列表中。结果KTable将具有<CustomerId, [List of Order]>类型的事件。

使用交互式查询,您可以查询状态存储,

StreamsBuilder builder = new StreamsBuilder();
KStream<String, Order> orderStream = builder.stream("orders");
KTable<String,ArrayList<Order>> orderTable = orderStream
      .groupBy((key,value)-> value .get("customerId"))
      .aggregate(()-> new ArrayList<Order>(),
                 (key,val,agg)-> agg.add(val),
                  Materialized.as("customer-orders")
                  .withValueSerde(ArrayListSerde())          
       ); 

它将创建一个物化视图“客户订单”,您可以通过其余端点进行查询。

您可以通过下面的链接将KTables公开为休息端点:

https://docs.confluent.io/current/streams/developer-guide/interactive-queries.html