• 关于多数据源(除自己数据库外,另一部分数据需通过接口调取第三方获取)的查询问题


    同样,还是一次工作上遇到的问题的记录,当时也是搞了挺久才搞出来的,虽然不太完美,但是误差方面在我的项目里还算可以接受,哪位老哥有更好的办法还请指导下,哪怕评论里留个网页链接我去看也好,多谢了。

    具体问题描述大致如下:

      客户需要app能查询出所有订单,分页并且按时间倒序排列,现在所有的消费订单数据在我们自己的数据库里,而所有的充值订单数据其实在第三方那里(其实我们自己也记录了一笔,但是数据结果不可靠,因此还是要取用对方的),关于从第三方获取数据的参数概括是(用户唯一标识,每页显示行数,当前页数),即(userId,pageSize,pageNo),其中pageSize要求小于50。

    经过思考,需要解决的问题主要在于:

      1.如何从第三方获取我需要的数据

      2.整合我们库里的数据,第三方获取的数据,进行时间倒序排列,并返回给app

    实际上第二点很好解决,只要写一个排序类,对整合后的数据进行排序即可,最主要难点在于第一点,如何确定调取第三方接口的入参pageSize和pageNo,然后还要把之前已经展示过的数据排除掉。

    具体解决方法如下:

      1.首先,我用了cache,用于记录app已展示的(消费记录数)(充值记录数),即(我方库数据展示量)(第三方数据展示量),暂定参数为ownother,当app端传的页数为第一页时,将这两个数据都置为0.

      2.查询接下来需要展示的数据中,我方的数据,这点没什么好说的,正常的查自己数据库即可,需要查出来的量为own<rownum<own+appPageSize,其中appPageSize是指app的入参,app端的页显示行数

      3.然后查询需要展示的数据中,第三方的数据,关于确定调取第三方接口入参的方法如下:

     1 /**
     2      * 获取第三方订单查询接口所需要的参数
     3      * @param start        起始数据量
     4      * @param end        结束数据量
     5      * @param size        展示数据量
     6      * @return
     7      * Map,包含两个参数,pagenum页数,pagesize页显示行数
     8      */
     9     public static Map<String,Integer> getWdPara(int start,int end,int size){
    10         Map<String,Integer> map=new HashMap<>();
    11         if (start<size||start/size<1) {
    12             map.put("pagenum", 1);
    13             map.put("pagesize", 10*((end/10)+1));
    14         }else{
    15             if (start/size==end/size) {
    16                 map.put("pagenum", (end/size)+1);
    17                 map.put("pagesize", size);
    18             }else {
    19                 map=getWdPara(start, end, size+1);
    20             }
    21         }
    22         return map;
    23     }

    其中三个参数的关系是end=start+size,实际上start入参的值就是other,而size入参的值就是appPageSize。而出参的两个参数就分别是调取第三方时候的入参pageSize和pageNo了。关于如何确定这个方法可以获取想要的参数,说起来有点绕,我数学也不太好,当时打了挺久的草稿,参照如下,如果看不懂直接跳过就好。。。因为我自己也经常忘记什么意思:

    默认app端展示数据量为10条,所以从第三方中获取的数据需要包含other+10条,因为根据时间倒序,这中间存在没有数据是消费数据,全是充值数据的情况,即所有展示数据均来自于第三方。

    第三方数据的起始-截止数据量      pageSize参数,即s    pageNo参数,即n  实际取到的数据量

    8-18                    20            1        1-20

    18-28                    15             2        15-30

    28-38                    20             2        20-40

    。。。

    一开始是这样草稿打下去的,后来找规律后发现,其实就和查自己数据库一样,保证查到的数据包含起始数据和终止数据即可,即       

    ( 页数-1)*页显示行数>起始数据,页数*页显示行数>终止数据

    然后进行几次举例验证后,就得出上述获取参数的方法了。

    至此,最难的一步已经完成了,即已经获取到所有需要的数据了。

      4.然后进行下一步,需要去除掉之前已经展示过了的数据,就如上面例子,我们获取到的数据量,其实是大于需要的数据量,有一部分数据可能之前已经展示了,因此在这里需要将之前展示了的数据去除掉,代码如下 

     1   /**
     2      * 处理订单数据,排除之前显示过的数据
     3      * @param dataList     待处理的list
     4      * @param start        数据起始
     5      * @param size         页显示行数
     6      */
     7     public static void dealList(List<Map<String, String>> dataList,int start,int size){
     8         int removeNum=start%size;
     9         for (int i = 0; i < removeNum; i++) {
    10             dataList.remove(0);
    11         }
    12     }

    即起始数据除以页显示行数,取余数,然后获取到的数据量从前往后删除这个余数量的数据即可,这个余数量即之前已经展示用过的数据量。和上面获取参数一样,这个计算方法,也是我自己写了好几个例子,然后找规律写出来的。。。数学不好,见谅,我也不知道逻辑上该怎么解释,反正根据例子找规律,发现这样写没问题。

      5.再然后就没啥问题了,要展示的充值数据,消费数据都已经全部获取到了,只要将一些参数名称处理下,确保保持一致,放在一个list里面,然后写个排序方法,根据订单时间进行倒序,排完序以后,获取前appPageSize个数据返回给前端即可,排序代码如下:

     1   /**
     2      * 数据进行排序,按照时间倒序排序
     3      * @param list
     4      */
     5     @SuppressWarnings("unchecked")
     6     public static void sortTimeMethod(List<Map<String,String>> list){
     7         Comparator comp= new Comparator<Map<String, String>>(){
     8             //返回值大于0时,两者交换顺序
     9             @Override
    10             public int compare(Map<String, String> p1,Map<String, String> p2){
    11                 String p1Date=Tools.processNull(p1.get("order_date"));
    12                 String p2Date=Tools.processNull(p2.get("order_date"));
    13                 if ("".equals(p1Date)
    14                         ||"".equals(p2Date)) {
    15                     return 0;
    16                 }else {
    17                     //如果o1时间早于等于o2时间,则o1排在后面
    18                     if (!DateUtil.formatDate(p1Date).after(DateUtil.formatDate(p2Date))) {
    19                         return 1;
    20                     }else {
    21                         return -1;
    22                     }
    23                 }
    24             }
    25         };
    26         Collections.sort(list, comp);
    27     }

      6.当然,这时候也别忘记更新cache里面的数据,根据最终返回给前端的数据,判断有多少消费数据和充值数据,对ownother进行相应的累加。

    以上就全部完成。不过就和我之前说的,有误差,很有局限性,跟我们使用场景有关,因此不是很具备参考性,相关说明如下:

      1.我们是APP展示用的,场景中无法跳页,也就是用户只能选择先看第一页,再看第二页数据,这样依次下排,如果存在跳页,我这个方法应该不行。

      2.当用户在看订单的同时,无法进行充值或消费操作,进行充值或消费等产生订单的操作后,重新来查询必定是从第一页开始,因此那种查了一会儿,突然增加一条订单了,这种情况是不会出现的,否则我这方法会存在问题,即cache里的值不准了,导致的结果就是查询的数据也不准了,有个订单会展示两次。


    可能看上去条理不是很清晰,有点混乱。。。但是尽力了,其实一开始没打算写,后来隔了半个多月,突然发现自己这个代码看不懂了,然后重新理解了半天,想想这个当初也是自己搞了挺久才弄出来的,怕以后又忘记了,于是此时开始写这篇随笔,本身就是隔了半个月后再写,思路就不是很清晰,结果写了一小半,客户又来事情了,于是忙去了。。。然后一段时间没闲下来,再然后忙着忙着就给忘了。。。。直到今天,已经是半年后了,再次来续写的时候,脑子就更乱了,强行看着半篇内容加自己原先的代码,将其续写完成。主要用处估计也就是以后自己如果遇到相同问题,给自己一个提点,一个思路,防止到时候自己脑子又转不过来。

                

  • 相关阅读:
    长沙雅礼中学集训-------------------day1(内含day0)
    17年 5月份刷题版
    manecher_回文串;
    后缀数组
    湖南集训
    好像又好久没更了;计算课noip模拟赛;
    dp的练习题;
    oj1638
    【noi】植物大战僵尸
    #日常吐槽
  • 原文地址:https://www.cnblogs.com/lilh/p/9958786.html
Copyright © 2020-2023  润新知