laravel搜索多个按空格分隔的单词

2022-08-30 19:32:21

我是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.'%')

请帮忙,提前致谢


答案 1

这是您使用 的方式,但首先要注意一些其他事项: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();

中有闭包,因为将子句括在括号中是一种很好的做法。例如,如果你的模型使用了,而你不会按照我的建议去做,那么你的整个查询就会被搞砸。whereor whereUserSoftDeletingScope


答案 2

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

您可以使用 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


推荐