29

当查询的数据来自多个数据源,有哪些好的分页策略?

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MjM5NDM4MDIwNw%3D%3D&%3Bmid=2448835423&%3Bidx=1&%3Bsn=ded729eb039d38881095d390cec0f712
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

概述

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

问题

BFFBviA.png!web

如上图,数据源可能来自不同 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 s")

}

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

}

}

小结

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

推荐阅读

iMrimef.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK