多重条件判读查询,代码如何优化?

A梦多啦
  • 193

题目描述

在一个列表数据中,我们可能会有一些筛选条件,这些筛选条件是用户随机勾选的。后端需要根据这些筛选条件做数据查询,就会涉及到某个筛选字段存在,其他的筛选字段不存在的情况。如果用大量的 if 去判断,代码就不够优雅,该如何优化?

相关代码

这里就用 PHP 代码作为示例代码了,正好手里有 PHP 代码。

// 前端请求传入筛选参数
$requestParams = [];
// 根据传入的筛选参数组装筛选条件
$searchWhere = [];
if (!empty($requestParams['id'])) {
    array_push($searchWhere, ['id', '=', $requestParams['id']);
}
if (!empty($requestParams['name'])) {
    array_push($searchWhere, ['name', '=', $requestParams['name']);
}
if (!empty($requestParams['score'])) {
    array_push($searchWhere, ['score', '>', $requestParams['score']);
}
if (!empty($requestParams['dates'])) {
    $date = explode(',', $requestParams['dates']);
    array_push($searchWhere, ['date', '>', $date[0]);
    array_push($searchWhere, ['date', '<', $date[1]);
}
// 查询数据
$items = DB::query()->where($searchWhere)->get();

你期待的结果是什么?实际看到的错误信息又是什么?

能够减少 if 条件的判断。最好是能封装成一个类什么的,来进行处理。减少这种重复、低效的代码。

回复
阅读 397
4 个回答
个人看法,不代表所有人

1,你的代码从性能层面讲,是最快的
2,你的代码维护角度讲,是容易让人看懂的,能看懂每一个参数是做什么用的,什么判断条件
3,如果所有的条件都为空,你会不会查全表哦

所以我觉得,这个代码没有必要去优化,看起来优雅和真正的维护性相比,我选维护性,当然了,如果重复的地方比较多,那就另说了,个人意见
// 前端请求传入筛选参数
$requestParams = ['id' => 1, 'name' => 'test', 'score' => 10, 'dates' => '2020-11-01,2020-11-12'];

// 根据传入的筛选参数组装筛选条件
$searchWhere = [];

foreach ($requestParams as $key => $value) {
    if($row = format($key, $value, $condition)) {
        $searchWhere[] = $row;
    }
}

function format($key, $value, $condition)
{
    //有特殊情况,增加配置这里的逻辑就好了
    $condition = ['id' => '=', 'name' => '=', 'score' => '>', 'dates' => 'range'];
    if($condition[$key] == 'range') {
        $value = explode(',', $value);
        return ["between {$value[0]}", 'and', $value[1]];
    }

    return [$key, $condition[$key], $value];
}
Array
(
    [0] => Array
        (
            [0] => id
            [1] => =
            [2] => 1
        )

    [1] => Array
        (
            [0] => name
            [1] => =
            [2] => test
        )

    [2] => Array
        (
            [0] => score
            [1] => >
            [2] => 10
        )

    [3] => Array
        (
            [0] => between 2020-11-01
            [1] => and
            [2] => 2020-11-12
        )

)

就根据你这个筛选条件,封装成一个函数返回就可以了。比如常见的:

  1. 分页:page, pageSize, 如果不传就默认第一页,20个
  2. 加载更多:start, size, 如果不传就是第一次
  3. 筛选字段:filter=id,score 后端字符串分割,如果比较复杂,比如大于多少,小于多少这种,就可以定义一个格式,或者直接使用json比较方便。

设计的时候考虑数据库查询是添加条件方不方便,就照着最简单的方式规范一下。

public function searchWhere()
{
    /*
    前端在提交搜索条件时,提交两组数据,一个组是查询的字段,一组是查询的值,顺序都要相互对应。
 { id:{eq}, name:{like}, age:{scope,operation}, date:{between,operation1,operation2}, }
 { 12, 张三 { 1,21 }, { 2020-01-12,2020-12-12 } } */
 // 前端传递的参数
 $requestParams = [];
    // 处理分页
 $pge = $requestParams['page'] ?? 1;
    $size = $requestParams['size'] ?? 20;
    // 处理请求参数
 /** @var array $searchFields 传入的查询字段 */
 $searchFields = $requestParams['fields'];
    /** @var object $searchValues 传入的查询值 */
 $searchValues = $requestParams['values'];
    // 循环处理查询条件
 $searchWhere = [];
    foreach ($searchFields as $key => $value) {
        if ($value[0] == 'eq') {
            array_push($searchWhere, ["$key", '=', $searchValues[$key]]);
        }
        if ($value[0] == 'like') {
            array_push($searchWhere, ["$key", 'like', '%' . $searchValues[$key] . '%']);
        }
        if ($value[0] == 'scope') {
            array_push($searchWhere, ["$key", $value[1], $searchValues[$key]]);
        }
        if ($value[0] == 'between') {
            array_push($searchWhere, ["$key", $value[1], $searchValues[$key]]);
            array_push($searchWhere, ["$key", $value[2], $searchValues[$key]]);
        }
    }
}

大概是这么个思路,没有用类的方式,看懂就行

function build_filter($mapParam, $mapConfig)
{
   $arrFilter = [];
   foreach($mapParam as $k => $v)
   {
       if(array_key_exists($k, $mapConfig) === false)
           continue;
       $op = $mapConfig[$k];
       if(is_callable($op) === true)
       {
           $arr = call_user_func($op, $v);
           foreach($arr as $filter)
               array_push($arrFilter, $filter);
       }
       else
       {
           $arrFilter[] = [$k, $op, $v];
       }
    }
    return $arrFilter;
}
$requestParams = [
    'id' => 2,
    'name' => 'test',
    'dates' => '2020-11-01,2020-11-02',
];
$mapFilterConfig = [
    'id' => '=',
    'name' => '=',
    'score' => '>',
    'dates' => function($data){
        $arrDate = explode(',', $data);
        return [
            ['date', '>', $arrDate[0]],
            ['date', '<', $arrDate[1]],
        ];
    },
];
$arrFilter = build_filter($requestParams, $mapFilterConfig);
var_dump(json_encode($arrFilter, JSON_UNESCAPED_UNICODE));

输出 [["id","=",2],["name","=","test"],["date",">","2020-11-01"],["date","<","2020-11-02"]]

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏