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

题目描述

在一个列表数据中,我们可能会有一些筛选条件,这些筛选条件是用户随机勾选的。后端需要根据这些筛选条件做数据查询,就会涉及到某个筛选字段存在,其他的筛选字段不存在的情况。如果用大量的 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 条件的判断。最好是能封装成一个类什么的,来进行处理。减少这种重复、低效的代码。

阅读 290
评论
    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
            )
    
    )
      • 516

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

      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]]);
                }
            }
        }
          • 3.2k

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

          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"]]

            撰写回答

            登录后参与交流、获取后续更新提醒

            相似问题
            推荐文章