【问题标题】:laravel search multiple words separated by spacelaravel 搜索多个以空格分隔的单词
【发布时间】:2015-03-31 22:57:32
【问题描述】:

我是 laravel 查询生成器的新手,我想搜索输入字段中输入的多个单词,例如,如果我输入“jhon doe”,我想获取任何包含 jhon 或 doe 的列

我已经看到/尝试过使用 php MySQL 的解决方案,但无法适应查询生成器

//1. exploding the space between the keywords 

//2. using foreach apend the query together

$query = "select * from users where";

$keywordRaw = "jhon doe";
$keywords = explode(' ', $keywordRaw );
foreach ($keywords as $keyword){
$query.= " first_name LIKE '%" + $keyword +"%' OR ";
}

我如何使用查询生成器来做到这一点

这是我到目前为止所拥有的,这样做的正确方法是什么,

$keywordRaw = "jhon doe";
//how do I explode this words and append them along with their appropriate query
$users = User::select('users.*')
->where('first_name', 'LIKE', '%'.$keywordRaw.'%')

请帮忙,提前谢谢

【问题讨论】:

    标签: php mysql laravel eloquent query-builder


    【解决方案1】:
     $keywordRaw = "jhon doe";
        $key = explode(' ',$keywordRaw);
        $users = User::select('users.*')
        ->whereIn('first_name',$key);
    

    这可行。whereIn 将根据您输入的关键字搜索名字。

    【讨论】:

    • whereIn 是明确的,即=,而 OP 想要like %value%,所以它不是那个。字符串中的双空格或其他空格也会使其无效。
    【解决方案2】:

    我在下面写了第一个解决方案,它成功了

    解决方案 1

    function fuzzySearch($keyword='jhon doe'){
       $queryText = implode('%',str_split($keyWord));
       return User::query()->where('first_name','LIKE',"%{$queryText}%")->get();
    }
    
    

    但是,当我在搜索中添加空格时,它会返回空结果,但它们存在于数据库中,因此我添加了 str_replace(" ","",$keyWord) 以删除空格,现在它可以工作了

    解决方案 2

    function fuzzySearch($keyword='jhon doe'){
       $queryText = implode('%',str_split(str_replace(" ","",$keyWord)));
       return User::query()->where('first_name','LIKE',"%{$queryText}%")->get();
    }
    
    

    注意 implode() 函数将关键字 jhon doe 转换为 j%h%o%n%d%o%e

    【讨论】:

      【解决方案3】:
      $string = 'john  doe';
      
      // split on 1+ whitespace & ignore empty (eg. trailing space)
      $searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY); 
      
      $users = User::where(function ($q) use ($searchValues) {
        foreach ($searchValues as $value) {
          $q->Where('name', 'like', "%{$value}%");
        }
      })->get();
      

      使用 'orWhere' 将为您提供每个关键字的结果,而不是关键字 1 + 关键字 2 的结果...所以一切都取决于您要查找的内容

      【讨论】:

        【解决方案4】:

        你可以使用这个包https://github.com/nicolaslopezj/searchable

        如果你不想使用包,也可以这样做

        $keywordRaw = "jhon doe";
        $users = User::where('first_name', 'LIKE', $keywordRaw.'%')
        ->orWhere('first_name', 'LIKE', '% '.$keywordRaw.'%')
        ->get();
        

        【讨论】:

          【解决方案5】:

          这就是您使用Query\Builder 的方式,但首先要补充一些注意事项:

          // user can provide double space by accident, or on purpose:
          $string = 'john  doe';
          
          // so with explode you get this:
          explode(' ', $string);
          array(
            0 => 'john',
            1 => '',
            2 => 'doe'
          )
          
          // Now if you go with LIKE '%'.value.'%', you get this:
          select * from table where name like '%john%' or name like '%%' or ...
          

          也就是说,您显然不能依赖explode,因为在上述情况下,您将获得所有行。

          所以,这就是你应该做的:

          $string = 'john  doe';
          
          // split on 1+ whitespace & ignore empty (eg. trailing space)
          $searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY); 
          
          $users = User::where(function ($q) use ($searchValues) {
            foreach ($searchValues as $value) {
              $q->orWhere('name', 'like', "%{$value}%");
            }
          })->get();
          

          where 中有闭包,因为将or where 子句括在括号中是一种很好的做法。例如,如果您的 User 模型使用了 SoftDeletingScope 而您不按照我的建议进行操作,那么您的整个查询就会一团糟。

          【讨论】:

          • 感谢@Jarek,我刚刚用我的其他连接表实现了它,对其进行了分页,并且运行良好,再次感谢
          【解决方案6】:

          您是否考虑过在 first_name 列上使用 FULLTEXT 索引?

          您可以使用 Laravel 迁移创建此索引,但需要使用 SQL 语句:

          DB::statement('ALTER TABLE users ADD FULLTEXT(first_name);');
          

          然后您可以对该字段运行相当高级的搜索,如下所示:

          $keywordRaw = "john doe";
          $keywords   = explode(' ', $keywordRaw);
          $users   = User::select("*")
                        ->whereRaw("MATCH (first_name)
                                    against (? in boolean mode)",[$keywords])
                        ->get();
          

          这将匹配包含单词“john”或“doe”的记录;请注意,这种方法将匹配整个单词,而不是子字符串(如果您使用 LIKE,可能会出现这种情况)。

          如果你想查找包含所有个单词的记录,你应该在每个关键字前面加上一个'+',像这样:

          $keywords   = '+'.explode(' +', $keywordRaw);
          

          您甚至可以按相关性进行排序,尽管这对于您的需求来说可能是多余的(并且与“所有”搜索无关)。像这样的:

          $users = User::select("*")
                         ->selectRaw("MATCH (first_name)
                                      against (? in boolean mode)
                                      AS relevance",[$keywords])
                         ->whereRaw("MATCH (first_name)
                                     against (? in boolean mode)",[$keywords])
                         ->orderBy('relevance','DESC')
                         ->get();
          

          这里有一篇很好的文章介绍了这种通用方法:

          http://www.hackingwithphp.com/9/3/18/advanced-text-searching-using-full-text-indexes

          【讨论】:

            【解决方案7】:

            试试这个..

               $searchQuery = "jhon doe"; 
            $searchTerms = explode(" ", $searchQuery); // Split the words
            $users = User::whereIn('FirstName', $searchTerms)->get();
            print_r($users);
            

            【讨论】:

              【解决方案8】:

              你可以尝试如下

              $keywordRaw = "jhon doe";
              $bindArr = explode(" ", $keywordRaw);
              
              $query = "select * from users where";    
              foreach ($i = 0; $i < count($bindArr); $i++) {
                  if ($i == 0) {
                      $query.= ' first_name LIKE "%?%"';
                  } else {        
                      $query.= ' or first_name LIKE "%?%"';
                  }
              }
              
              $sth = $dbh->prepare($query);
              $sth->execute($bindArr);
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-06-04
                • 1970-01-01
                • 2012-07-28
                • 1970-01-01
                • 2010-12-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多