Spark 项目实战之数据服务分析(六)

可疑对象分析

可疑对象的处理,可以从他行迹的几个坐标距离,与事件差进行对比。如果符合逻辑,可以认为是当前对象是无可疑的。如果是可疑的,即将结果先保存起来,进入可疑对象库。

  1. 通过获取时间段的数据;
  2. 根据被监测对象的 RSFZ 聚合数据;(RSFZ: SBBH_TGSJ_JWZB)
  3. 根据判定规则:处理每个监测对象的 RSFZ 的聚合数据,将符合负责的数据唯一标识放到累加器中;
  4. 获取家属器的唯一标识,从表中查询相关记录,存入 mysql 中。

代码

public class VerifyCompute {
        String sql = "select * from t_alldata t where t.tgsj";
        Dataset<Row> allFromTime = spark.sql(sql);

        JavaRDD<Row> resultRDD = allFromTime.javaRDD();
        /**
         * 从数据中获取必要的列名来转换成 PairRDD
         */
        JavaPairRDD<String, String> pairRDD = resultRDD.mapToPair(new PairFunction<Row, String, String>() {
            @Override
            public Tuple2<String, String> call(Row row) throws Exception {
                String rsfz = row.getAs("RSFZ");
                String id = row.getAs("ID");
                String tgsj = row.getAs("TGSJ");
                String sbbh =row.getAs("SBBH");
                String jwzb = row.getAs("JWZB");

                String tuple01 = rsfz;
                String tuple02 = id + "_" + jwzb + "_" + tgsj+"_"+sbbh;
                return new Tuple2<String, String>(tuple01, tuple02);
            }
        });

        /**
         * 对相同身份证的数据对 id + "_" + jwzb + "_" + tgsj 进行叠加,这样就可以
         * 获取 通过时间 和 经纬坐标。
         */
        JavaPairRDD<String, String> reduceRDD = pairRDD.reduceByKey(new Function2<String, String, String>() {
            private static final long serialVersionUID = 1L;
            @Override
            public String call(String v1, String v2) throws Exception {
                return v1 + "&" + v2;
            }
        });

        //创建累加器,用于添加计算后的数据。
        CollectionAccumulator<String> acc = jsc.sc().collectionAccumulator();

        /**
         * 由于不能在 map foreach 中调用RDD,所以可以用累加器将 id 封装起来。
         */
        reduceRDD.foreach(new VoidFunction<Tuple2<String, String>>() {
            private static final long serialVersionUID = 1L;
            @Override
            public void call(Tuple2<String, String> s2) throws Exception {
                String IDCard = s2._1;
                String[] values = s2._2.split("&");

                for (int i = 0; i < values.length; i++) {
                    for (int k = i + 1; k < values.length; k++) {
                        String value1 = values[i];
                        String value2 = values[k];

                        String[] item1 = value1.split("_");
                        String[] item2 = value2.split("_");

                        String id1 = item1[0];
                        String lon1 = item1[1];
                        String lat1 =item1[2];
                        String tgsj1 = item1[3];

                        String id2 = item2[0];
                        String lon2 = item2[1];
                        String lat2 =item2[2];
                        String tgsj2 = item2[3];

                        double subHour = TimeUtils.getSubHour(tgsj1, tgsj2);
                        double distance = MapUtils.getLongDistance(Double.valueOf(lon1), Double.valueOf(lat1),Double.valueOf(lon2),Double.valueOf(lat2));

                        Integer speed = SpeedUtils.getSpeed(distance, subHour);

                       //核心操作
                        if (speed > 5) {
                            acc.add(id1 + "_" + id2);

                            /**
                             * 如果这里就进行 RDD,就会发生 空指针异常。所以,要在map、foreach算子中调用 dataFrame 或 RDD 方法
                             */
                        }
                    }
                }
            }
        });

        List<String> accValue = acc.value();

        for(String id: accValue) {
            Dataset<Row> resultDF3 = spark.sql("select RSFZ,GRXB,PSQK, TGSJ," +
                    "SBBH,JWZB from t_alldata where id in (" + id.split("_")[0] + "," + id.split("_")[1] + ")");
            resultDF3.show(20);

            Dataset<Row> resultDF4 = resultDF3.withColumn("CreateTime", functions.lit(new Date().getTime()));
            resultDF4.write()
                    .format("jdbc")
                    .option("url", "jdbc:mysql://bigdata03:3306/test?characterEncoding=UTF-8")
                    .option("dbtable", "t_verify_result")
                    .option("user", "root")
                    .option("password", "123456")
                    .mode(SaveMode.Append)
                    .save();
        }
    }
}

实操实现

  1. 在 mysql 数据库中创建表
CREATE TABLE t_verify_result(
RSFZ text,
GRXB text,
PSQK text,
TGSJ text,
SBBH text,
JWZB text,
CJSJ text
)charset utf8 collate utf8_general_ci;
  1. 复用 hive 中 t_people_together 表的数据。
  2. 使用 submit 执行
./spark-submit 
--master spark://bigdata01:7077 
--class com.monitor.compare.VerifyCompute 
--deploy-mode client 
/root/monitoranalysis-1.0-SNAPSHOT.jar

这样就可以把数据以 RSFZ | GRXB | PSQK | TGSJ SBBH | JWZB | CJSJ 方式在数据库中。

第二种方式

这种方式采用纯 SQL 来进行处理
首先自定义一个 UDF

public class ComputeUDF implements UDF1<String, String> {

    @Override
    public String call(String s) throws Exception {
        StringBuilder sbResult = new StringBuilder();

        String value = s;
        String[] values = s.split("&");

        // 对数据进行遍历,将数据中的 时间与经纬度取出来计算出不同的 speed。
        for (int i = 0; i < values.length; i++) {
            for (int k = i+1; k < values.length; k++) {
                String value1 = values[i];
                String value2 = values[k];
                String[] item1 = value1.split("_");
                String[] item2 = value2.split("_");

                String id1 = item1[0];
                String lon1 = item1[1];
                String lat1 = item1[2];
                String tgsj1 = item1[3];

                String id2 = item2[0];
                String lon2 = item2[1];
                String lat2 = item2[2];
                String tgsj2 = item2[3];

                //System.out.println("id= "+id1+" ,lon= "+lon1+" ,lat= "+lat1+" ,tgsj= "+tgsj1);
                double subHour = TimeUtils.getSubHour(tgsj1, tgsj2);

                // System.out.println("subHour= "+subHour);
                double distanct = MapUtils.getLongDistance(Double.valueOf(lon1), Double.valueOf(lat1), Double.valueOf(lon2), Double.valueOf(lat2));

                //System.out.println("distanct= "+distanct);
                Integer speed = SpeedUtils.getSpeed(distanct, subHour);

                //System.out.println("speed= "+speed);
                if (speed > 5 && speed != null) {
                    if (sbResult.length() > 0) {
                        sbResult.append("&").append(id1 + "_" + id2);
                    } else {
                        //首次 append 到StringBuilder。
                        sbResult.append(id1 + "_" + id2);
                    }
                }
            }
        }
        return sbResult.toString().length() > 0 ? sbResult.toString() : null;
    }
}

其次,在 Spark程序中使用该方法

Dataset<Row> sqlDF = spark.sql("select rsfz,verifyValue from(" +
                "select rsfz,getVerify(concat_ws('&',collect_set(concat_ws('_',id,jwzb,tgsj)))) " +
                "as verifyValue from t_people_together group by rsfz) where verifyValue is not null");

如果看不懂上述 sql 语句,可以拆分为三个 sql

spark.sql("select RSFZ,concat_ws('_',ID,JWZB,TGSJ) as concatValue from t_alldata").show(false);

spark.sql("select RSFZ,concat_ws('&',collect_set(concat_ws('_',ID,JWZB,TGSJ))) " +
               "as concatValue from t_alldata group by RSFZ").show(false);

getVerify 返回 id1_id2,所以显示的结果是 <RSFZ id1_id2>
spark.sql("select RSFZ,getVerify(concat_ws('&',collect_set(concat_ws('_',ID,JWZB,TGSJ)))) " +
                "as verifyValue from t_alldata group by RSFZ").show(false);

实际操作

  1. 创建 mysql 数据库表
CREATE TABLE t_verify_result2(
RSFZ text,
GRXB text,
PSQK text,
TGSJ text,
SBBH text,
JWZB text,
CJSJ text
)charset utf8 collate utf8_general_ci;
  1. 执行 spark
./spark-submit 
--master spark://bigdata01:7077 
--class com.monitor.compare.VerifyCompute2
--deploy-mode client 
/root/monitoranalysis-1.0-SNAPSHOT.jar

实例代码

https://github.com/yy1028500451/MonitorAnalysis/tree/master/src/main/java/com/monitor/compare

猜你喜欢

转载自blog.csdn.net/dec_sun/article/details/89715699