从druid中查出的结果集根据不同筛选条件进行修正

需求如下

由于运营人员将分成比例设为0,导致publisherId=10714; media_id=2454; posid=2454105在[20180612,20180619]之间的estimated earnings数据为0

ecmp是千次展现的预估费用,公式是用estimated earnings除以impressions,再除以1000

所以修正主要是在过滤条件或者选择维度满足条件时做修正,因为情况比较多,下面先简单逐一列一下:

filters:

media_id=2454 或者 pos_id=2454105

fitler中如果包含location条件,因为维度太细,也不做修正

Dimension

选择app维度且media_id=2454

选择pos维度且pos_id=2454105

维度默认是包含day的

维度中如果包含hour,或者location这些更细粒度的维度,则不修正


取数的流程是,后台先根据filter,demension,时间区间,拼凑一个query的json串,然后给druid服务器发送query请求

结果以json格式返回

因为拼凑条件不同,拼成的json串也不同,返回的json串也有所不同

本来我以为问题很简单,但是最后我提交了四版代码,在我们贴代码之前,先整理一下哪些情况下需要修正estimated earnings,

因为不修正的情况太多,所以我们详细讨论下需要修正的情况

1.filter中如果有location条件,一律不作修正

2.filter中如果有app条件,且等于2545,要做修正,这里有个问题我们下面再说

3.filter中如果有pos条件,且等于2454105,要做修正

假设filter中没有选任何条件,下面我们单独考虑dimension

4.dimension中如果有app维度,且等于2454,要做修正

5.dimension中如果有pos维度,且等于2454105,要做修正

6.dimension中如果有hour维度或者location维度,一律不需要修正

乍一看也就六种情况,最后看下我写的代码,代码大概流程如下

for (json数组结果集) {

    if (满足条件) {

        修正estimated earnings;

    }

}

下面说下filter中如果有media_id=2454的情况,此时如果汇总维度是pos维度,一个media下面如果有10个pos,直接修正的化,

会造成2454106那些数据也被修正,所以这个地方要注意,代码中也有体现

下面的代码都是在遍历结果集的循环中,循环中的每一项都是一天的数据,每一项并不是一个javabean,而是一个JSONObject


因为分支条件太多,后来我想出来使用标志位,保证每个修正只会被执行一次,这样就不需要大量的else if结构

那些else if的部分其实还可以通过标志位再改造,但是我实在不想看这个代码了

什么条件都不选,dimension不选,filters也不选,是第四版时测试帮我测出来的,开始我一直没考虑这种情况

因为这个代码挺有代表性的,我就把这个Java文件保存下来了

因为我没有粘贴结果集的json结构,所以想直接看懂这个代码还是有难度的

问自己一个问题,如果让自己重新设计这个报表系统,你会怎么做?

你会放弃JSONObject,而使用javabean吗

你会时间条件也归入查询条件吗

你会把数据先读入mysql,然后用查询条件拼凑sql语句,然后把结果集封装成javabean的链表吗

如果用sql语句写查询,应该会容易很多,维度就是group by,filters就是where中的条件,绝对比现在用json条件查询简单多了

复杂的地方就是在于拼凑动态的sql,生成动态的javabean

我想这样实现更简单:

1.如果用sql查询,在service中直接通过字符串拼接的方式,生成select结果字段,where条件和group by条件,传递给mybatis

2.如果用json查询,在service中根据filter和汇总维度生成query用的json串

3.结果集一定是javabean的链表

4.取出多少列是动态指定的,在select后面传动态参数。但是javabean包含最全面的字段,对没有要展现的字段,可以全部赋null,反正前端也不要看

现在项目中的这个结果集合是一个JSONArray,前端让取不同的列,那JSONObject也不相同,导致解析的时候还得先判断哪些列被取到了,真是麻烦


我们继续深入思考,如果结果集是List<bean>,遍历list过程中,只要判断pos_id=2454105或者media_id=2454,就做修正,一行代码就完了啊

为啥这里会这么复杂呢,原因在于只有选了app或者pos维度下,结果集中才有pos_id和media_id的数据,如果只是filter中包含media_id或者pos_id,那结果集中就不包含这两个字段,那就无法在结果集中判断pos_id和media_id,这是修正如此复杂的根本原因。

所以如果重新设计的化,要保证一件事:

查出的javabean是包含所有字段的,对于不能展示的字段(比如分成比例)可以置为null,但是where条件,汇总维度这些字段在每个bean中都要能取到


刚看这个系统的时候,到处都是JSONObject,JSONArray,感觉这个玩意好屌啊

JSONObject完全可用替代javabean啊,确实是这样

JSONArray完全可以取代数组啊,确实是这样,甚至更好,因为JSONArray可以存放不同类型的数据

引申一下

其实用map完全可以构建javabean,

map user = new HashMap();

user.set(name, "luoluo");

user.set(age, 18);

用JSONObject完全可以取代javabean,

JSONObject user = new JSONObject();

user.put(name, "luoluo");

user.put(age, 18);

用JSONObject还可以做容器,不过真要做容器的化,感觉还是map好一点

JSONObject collection = new JSONObject();

collection.put(key1, bean1);

collection.put(key1, bean2)


领导在开会的时候说,做系统最重要的两件事:

1.权限

2.报表

这个系统能实现的功能很简单,但是这帮人硬是把他做成这样复杂

传参全部是JSONObject,有必要吗

构造一个javabean就可以,非要用JSONArray存储一个bean,有必要吗

那么多继承关系有必要吗

那么多format函数有必要吗

那么简单的地方非要用线程池,有必要吗

在看代码过程中,时刻问自己一个问题:

这个东西如果让你设计,你怎么做?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值