Возвращать строки на основе поиска по нескольким полям - PullRequest
0 голосов
/ 01 июля 2018

Допустим, у меня есть таблица с полями:

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 голосов
/ 02 июля 2018

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 записи. Первая запись - лучший матч.

Для получения дополнительной информации проверьте эту страницу MySQL

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...