根据多字段搜索返回行

时间:2018-07-01 09:41:14

标签: php sql regex laravel-5

让我们说我有一个带有字段的表:

name, email, designation, city

我想要的是用户可以通过在单个搜索框中输入单个单词或多个单词来搜索记录。例如。 ABC abc@gmail.com

现在我正在使用这样的东西:

$keywords = $request->get('search');
$searchValues = preg_split('/\s+/', $keywords, -1, PREG_SPLIT_NO_EMPTY);

$users = DB::table('users')
                    ->select('name', 'email',  'designation', 'city')
                    ->where(function ($query) use($searchValues){

                        foreach ($searchValues as $value)
                        {
                            $query->orWhere('name', 'like', "%{$value}%")
                                  ->orWhere('email', 'like', "%{$value}%")
                                  ->orWhere('designation', 'like', "%{$value}%")
                                  ->orWhere('city', 'like', "%{$value}%");
                        }
            })->latest('users.created_at')->paginate($perPage);

这有效,但是存在一个问题,它返回所有具有名称'ABC'的用户,而不是仅返回具有 name ='ABC'的行>和 email='abc@gmail.com'

我该如何实现?

1 个答案:

答案 0 :(得分:0)

MySQL有一个鲜为人知的功能,称为MATCH (column1,column2) AGAINST ('keyword1 keyword2' IN BOOLEAN MODE),专为全文搜索而设计。它类似于类似google的搜索,其中关键字与最匹配为最优先结果的列值匹配。

请注意,您必须先清理搜索查询。某些符号在匹配中是禁止的。我编写了此函数来清理它并准备搜索查询:

function returnMatchQuery($keyword)
{
    $keyword  = trim(str_replace(['+', '-', '~', '>', '<', '(', ')', '*', '´', '`'], ' ', $keyword));
    $keywords = collect(explode(' ', $keyword));
    $keywords = $keywords->map(function ($val)
    {
        return '+' . $val;
    });

    return implode(' ', $keywords->toArray());
}

在主要功能中:

$search_query = returnMatchQuery($keywords);
DB::table('users')->selectRaw("name,email,designation,city")
    ->whereRaw("MATCH (name,email,designation,city) AGAINST ('{$search_query}' IN BOOLEAN MODE)")
    ->->paginate($perPage);

请注意,已释放->latest('users.created_at')。您可能必须添加,也可以不必添加。结果可能有1条以上的记录。第一记录是最佳匹配。

有关更多信息,请检查this MySQL page