Spark 2.4 Java环境下MapType聚合去重与键值过滤问题求助
问题解决思路
问题根因说明
- 重复Map键问题:你直接对
name分组后调用map_from_arrays,传入的collect_list("make")会保留同一用户下所有重复的品牌值,Map结构虽然允许重复键,但通过getItem(key)取值时仅会返回第一个匹配键对应的value,这也是第二个查询结果不符合预期的直接原因。 - 统计字段错误问题:John的BMW键对应的第一个值是白色的2020款,你直接取
getItem("BMW").getItem("colour")只能拿到第一个值的颜色,自然无法匹配到黑色的记录。
解决方法
1. 生成键唯一、同品牌值合并为数组的Map
你需要先做两层分组:先按name+make分组收集同品牌的所有车辆信息,再按name分组构建Map,修改后的聚合逻辑如下:
// 第一步:按用户+品牌分组,收集同品牌所有车辆信息 Dataset<Row> intermediateDf = spark.createDataFrame(getData(), getSchema()) .groupBy("name", "make") .agg(collect_list(struct("yr", "colour")).as("car_list")); // 第二步:按用户分组,构建键唯一的Map Dataset<Row> df = intermediateDf.groupBy("name") .agg(map_from_arrays(collect_list("make"), collect_list("car_list")).as("cars")); df.show(false); // 此时输出符合你预期的Output 1
2. 正确统计是否存在对应颜色的车辆
现在Map的value是数组类型,你可以用Spark 2.4提供的exists函数判断数组中是否存在符合条件的元素,查询逻辑修改如下:
df.select(col("name"), when(expr("exists(cars['BMW'], x -> x.colour = 'white')"), 1).otherwise(0).as("hasWhiteBMW"), when(expr("exists(cars['BMW'], x -> x.colour = 'black')"), 1).otherwise(0).as("hasBlackBMW"), when(expr("exists(cars['Toyota'], x -> x.colour = 'white')"), 1).otherwise(0).as("hasWhiteToyota") ).show();
修改后的Output 2结果会正确显示John的hasBlackBMW值为1。
内容的提问来源于stack exchange,提问作者Ranganath Tirumala
相关产品推荐
相关产品推荐

