【发布时间】:2021-07-30 00:06:51
【问题描述】:
我有一个后端数据存储为 Redis 的应用程序。该应用程序(界面)为用户提供了一个必须支持搜索、分页、排序和过滤的表格。
我的 Redis 设计包括使用排序集和标准键:值对。例如,考虑一家二手车经销商。假设我有一个集合,toyota 的成员是与该品牌相关的所有待售汽车的列表。每个成员都是汽车型号和与实体汽车相关的一些唯一标识符的组合。
toyota
- corolla:100
- corolla:200
- corolla:300
- sienna:100
- sienna:200
该集合的每个成员都有一个单独的键,例如toyota:corolla:100,其中的值是一个包含有关该特定汽车的各种信息的对象:
{
id: 100,
brand: "Toyota",
model: "Corolla",
color: "red",
cost: 15000
}
了解这种基本数据关系后,我发现自己处于一个场景中,我希望通过每个键的对象中包含的某些属性来提供对这个前端表中的数据进行排序的能力。例如,汽车的颜色。当然,为此,我需要比较所有对象。
我的困境是如何在考虑分页的同时实现这一点。实际上,我的集合不是汽车,它们很容易包含数千名成员。但是数据关系是同一个概念。我不想为了确定这种排序而必须获取所有键,因为它违背了分页的目的。
我会澄清,我不是在我的 API 层中人为地对结果进行分页。我通过利用zrangebylex(提供一些基本排序)以及限制偏移量直接限制redis结果来实现分页。
$results = [];
$cars = $redis->zRangeByLex("toyota", '-', '+', 0, 1);
foreach( $cars as $car ) {
$results[] = json_decode($redis->get($car), true);
}
// example $cars return:
// [ "corolla:100", "corolla:200" ]
// example $results return:
// [
// { id: 100, brand: "Toyota", model: "Corolla", color: "red", cost: 15000 },
// { id: 200, brand: "Toyota", model: "Corolla", color: "blue", cost: 14000 },
// ]
我想避免人为地对结果进行分页,因为在每次 API 调用中获取数千条记录,然后遍历它们,花费的时间比可接受的要长。
我还要注意,在搜索方面,我正在使用 zscan 来搜索集合——这并不理想,因为这意味着我受到每个集合中成员值的限制。
$search = "corolla"; # user search term
$cars = []; # result container
$it = NULL; # iterator
$redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);
while($matches = $redis->zScan('toyota', $it, "*{$search}*")) {
foreach($matches as $key => $score) {
$cars[] = $key;
}
}
// example $cars return:
// [ "corolla:100", "corolla:200", "corolla:300" ]
虽然我可以在 SQL 环境中重新设计此应用程序并相对轻松地实现所有这些功能,但我更感兴趣的是使用 Redis 来完成这项工作。什么是更合适的 Redis 设计/模式,它将支持我想在这个前端表中实现的所有功能(排序、分页、搜索、过滤)?
【问题讨论】: