zoukankan      html  css  js  c++  java
  • 当查询的数据来自多个数据源,有哪些好的分页策略?

    概述

    在业务系统开发中,尤其是后台管理系统,列表页展示的数据来自多个数据源,列表页需要支持分页,怎么解决?

    问题

    如上图,数据源可能来自不同 DB 数据库,可能来自不同 API 接口,也可能来自 DB 和 API 的组合。

    我这也没有太好的解决方案,接到这样的需求,肯定首先和需求方沟通,这样分页是否合理。

    无非就两种方案:

    • 数据定期同步,首先将查询的数据汇总到一个地方,然后再进行查询分页。
    • 内存中分页,首先将查询的数据存放到内存,然后再进行查询分页。

    如果以某一数据源进行分页,其他字段去其他数据源获取,这样还好处理一些。

    如果以多个数据源融合后再分页的话,就数据定期同步 或 内存中分页吧。

    数据定期同步方案可以根据实际情况去设计同步频率,至于同步到 ES/MySQL/MongoDB 自己决定即可。

    关于内存中分页方案,下面分享两个小方法,供参考。

    PHP 方法

    $data = [
        0 => ['name' => "姓名1", 'age' => "年龄1"],
        1 => ['name' => "姓名2", 'age' => "年龄2"],
        2 => ['name' => "姓名3", 'age' => "年龄3"],
        3 => ['name' => "姓名4", 'age' => "年龄4"],
        4 => ['name' => "姓名5", 'age' => "年龄5"],
        5 => ['name' => "姓名6", 'age' => "年龄6"],
        6 => ['name' => "姓名7", 'age' => "年龄7"],
        7 => ['name' => "姓名8", 'age' => "年龄8"],
        8 => ['name' => "姓名9", 'age' => "年龄9"],
        9 => ['name' => "姓名10", 'age' => "年龄10"],
    ];
    
    /**
     * 数组分页
     * @param array $arrayData 数组数据
     * @param int   $page      第几页
     * @param int   $pageSize  每页展示条数
     * @return array
     */
    function arrayToPageData($arrayData = [], $page = 1, $pageSize = 10)
    {
        $arrayData = array_values((array)$arrayData);
        $pageData['list'] = array_slice($arrayData, ($page - 1) * $pageSize, $pageSize);
        $pageData['pagination']['total'] = count($arrayData);
        $pageData['pagination']['currentPage'] = $page;
        $pageData['pagination']['prePageCount'] = $pageSize;
        return $pageData;
    }
    
    echo json_encode(arrayToPageData($data, 2, 3));
    

    输出:

    {
        "list": [
            {
                "name": "姓名4",
                "age": "年龄4"
            },
            {
                "name": "姓名5",
                "age": "年龄5"
            },
            {
                "name": "姓名6",
                "age": "年龄6"
            }
        ],
        "pagination": {
            "total": 10,
            "currentPage": 2,
            "prePageCount": 3
        }
    }
    

    Go 方法

    package main
    
    import (
    	"encoding/json"
    	"fmt"
    )
    
    type User []struct {
    	Name string `json:"name"`
    	Age  string `json:"age"`
    }
    
    type Pagination struct {
    	Total        int `json:"total"`
    	CurrentPage  int `json:"currentPage"`
    	PrePageCount int `json:"prePageCount"`
    }
    
    type ListPageData struct {
    	List       User `json:"list"`
    	Pagination Pagination `json:"pagination"`
    }
    
    func main() {
    	jsonStr := `[{"name": "姓名1","age": "年龄1"},
    		{"name": "姓名2","age": "年龄2"},
    		{"name": "姓名3","age": "年龄3"},
    		{"name": "姓名4","age": "年龄4"},
    		{"name": "姓名5","age": "年龄5"},
    		{"name": "姓名6","age": "年龄6"},
    		{"name": "姓名7","age": "年龄7"},
    		{"name": "姓名8","age": "年龄8"},
    		{"name": "姓名9","age": "年龄9"},
    		{"name": "姓名10","age": "年龄10"}
    	]`
    
    	var user User
    	err := json.Unmarshal([]byte(jsonStr), &user)
    	if err != nil {
    		fmt.Println(err.Error())
    	}
    
    	page := 2
    	pageSize := 3
    	pageData := ArraySlice(user, page, pageSize)
    
    	listPageData := ListPageData{}
    	listPageData.List = pageData
    	listPageData.Pagination.Total = len(user)
    	listPageData.Pagination.CurrentPage = page
    	listPageData.Pagination.PrePageCount = pageSize
    
    	jsonData, _ := JsonEncode(listPageData)
    	fmt.Println(jsonData)
    }
    
    func JsonEncode(v interface{}) (string, error) {
    	bytes, err := json.Marshal(v)
    	if err != nil {
    		return "", err
    	}
    	return string(bytes), nil
    }
    
    func ArraySlice(u User, page int, pageSize int) User {
    	offset := (page - 1) * pageSize
    	if offset > int(len(u)) {
    		panic("offset: the offset is less than the length of u")
    	}
    	end := offset + pageSize
    	if end < int(len(u)) {
    		return u[offset:end]
    	}
    	return u[offset:]
    }
    

    输出:

    {
        "list": [
            {
                "name": "姓名4",
                "age": "年龄4"
            },
            {
                "name": "姓名5",
                "age": "年龄5"
            },
            {
                "name": "姓名6",
                "age": "年龄6"
            }
        ],
        "pagination": {
            "total": 10,
            "currentPage": 2,
            "prePageCount": 3
        }
    }
    

    小结

    如果你有更好的方案,欢迎留言评论 ~

    推荐阅读

  • 相关阅读:
    Warning:detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
    Ubuntu16.04安装K8s步骤和踩坑记录【不错】
    修改主机名(/etc/hostname和/etc/hosts区别)
    Windows10内置Linux子系统初体验
    Docker Swarm常用命令
    Docker Swarm集群部署
    Docker容器CPU、memory资源限制
    Docker监控容器资源的占用情况
    修改Docker容器启动配置参数
    sort-colors——排序3种数字
  • 原文地址:https://www.cnblogs.com/xinliangcoder/p/12565461.html
Copyright © 2011-2022 走看看