【问题标题】:How to bring the exact match first and then the partial match after a search如何在搜索后先进行完全匹配,然后再进行部分匹配
【发布时间】:2020-05-06 15:25:11
【问题描述】:

我有以下查询,在搜索框中搜索后会产生结果。它工作正常,只是它不会首先带回更具体的结果。例如,如果我搜索“Learn Laravel”,它会首先带来包括“learn”和“laravel”的结果,然后它会带来两者都有的结果。 我试图让查询首先带来确切的结果,然后带来包含这两个词之一的结果。

$searchValues2 = preg_split('/\s+/', $query, -1, PREG_SPLIT_NO_EMPTY); 
                  $posts = DB::table('gl as g')  
                    ->join('subcat as a', 'a.id', '=' , 'g.subcat')
                    ->join('steps as s', 's.goal_id','=', 'g.id')
                    ->join('users as u', 'g.user_id', '=' , 'u.id')
                    ->join('country as c', 'c.id', '=' , 'g.country')

                     ->where(function ($q2) use ($searchValues2) {
                      foreach ($searchValues2 as $value2) {
                        $q2->orWhere(DB::raw("g.title"), 'LIKE', "%{$value2}%");
                        $q2->orWhere(DB::raw("s.step"), 'LIKE', "%{$value2}%");
                      }
                    })

                    ->where('g.draft_flag', '!=', 1) 
                 ->orderby('g.created_at', 'desc') 
                 ->take(40)
                 ->groupby('g.id')
                 ->select('g.title as title', 'a.subcat as categ', 'g.id as id', 'u.id as u_id', 
                 'u.first_name as f_name', 'u.last_name as l_name', 'a.subcat as subcat','g.tlike as 
                  tlike','u.avatar as avatar','c.country as country')
                  ->get();

【问题讨论】:

  • 您可以尝试构建orderBys,类似于带有case 语句的where 子句。 CASE when g.title = '$value2' THEN 0 else 1 END; 等。不过,我建议不要从用户输入中使用未经处理的值构建原始语句。您应该使用绑定而不是将$value2 直接放在字符串中以避免SQL 注入。

标签: php mysql laravel


【解决方案1】:

你不能用 LIKE 语法来做到这一点。有一些技巧可以用来给 LIKE 语法打分,但在你的情况下,我认为它们不起作用。 您可以尝试根据匹配数对集合进行排序,但更好的方法是使用全文搜索。

首先你应该添加全文搜索索引。

ALTER TABLE gl ADD FULLTEXT title_fulltext (title)

然后: ->select(['....', DB::raw('MATCH (title) AGAINST (\''.$query.'\')')]) ->whereRaw('MATCH (title) AGAINST (?)' , array($query))

【讨论】:

    【解决方案2】:

    我将全文搜索添加到要搜索的表中。这里的说明:

    https://laravel-news.com/laravel-8-79-0

    为了获得全文搜索,然后进行类似搜索,我通过使用排名进行两次搜索,然后按排名进行联合搜索。

    $query1=Product::query();
    $query1->whereFulltext(['name'],request()->search,['language'=>'english'])  
        ->Live()
        ->select('*')
        ->addSelect(DB::raw('1 as rank'));
    
    
    $query2=Product::query();
    $query2
        ->where('name', 'ilike', '%'.request()->search.'%')
        ->orWhere('description', 'ilike', '%'.request()->search.'%')
        ->Live()
        ->select('*')
        ->addSelect(DB::raw('2 as rank'));
    
    products=$query1->union($query2)
                        ->orderBy('rank','asc')
                        ->limit(10)
                        ->get();
    
    $products->unique('id')->values(); //to get rid of duplicates`
    

    【讨论】:

      猜你喜欢
      • 2020-03-27
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多