1. 程式人生 > >關於多資料來源(除自己資料庫外,另一部分資料需通過介面調取第三方獲取)的查詢問題

關於多資料來源(除自己資料庫外,另一部分資料需通過介面調取第三方獲取)的查詢問題

同樣,還是一次工作上遇到的問題的記錄,當時也是搞了挺久才搞出來的,雖然不太完美,但是誤差方面在我的專案裡還算可以接受,哪位老哥有更好的辦法還請指導下,哪怕評論裡留個網頁連結我去看也好,多謝了。

具體問題描述大致如下:

  客戶需要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裡的值不準了,導致的結果就是查詢的資料也不準了,有個訂單會展示兩次。

 


可能看上去條理不是很清晰,有點混亂。。。但是盡力了,其實一開始沒打算寫,後來隔了半個多月,突然發現自己這個程式碼看不懂了,然後重新理解了半天,想想這個當初也是自己搞了挺久才弄出來的,怕以後又忘記了,於是此時開始寫這篇隨筆,本身就是隔了半個月後再寫,思路就不是很清晰,結果寫了一小半,客戶又來事情了,於是忙去了。。。然後一段時間沒閒下來,再然後忙著忙著就給忘了。。。。直到今天,已經是半年後了,再次來續寫的時候,腦子就更亂了,強行看著半篇內容加自己原先的程式碼,將其續寫完成。主要用處估計也就是以後自己如果遇到相同問題,給自己一個提點,一個思路,防止到時候自己腦子又轉不過來。