Eloquent ORM - concat w query builder

0

Cześć,

piszę pewną aplikację i mam problem jak napisać jedno zapytanie z query buildera.

W bazie danych mam dwie kolumny - IMIE oraz NAZWISKO.

Potrzebuje Ajaxem wyciągnąć dane z bazy na podstawie wpisywanych danych w inpucie na stronie (coś na zasadzie Facebookowej wyszukiwarki, piszemy imie i nazwisko, a z każdą kolejną litera pojawiają się pod spodem coraz trafniejsze sugestię).

Napisałem juz działający skrypt, który porównuję wpisywany string z IMIENIEM albo (OR) NAZWISKIEM.

Czyli jak dajmy na to mamy w bazie JAN KOWALSKI. To po wpisaniu JAN wyskoczy mi prawidłowo wspomniany użytkownik. Tak samo kiedy wpiszę KOWALSKI

 $user = User::where('name', 'like', '%' . $request['name'] . '%')
                    ->orWhere('surname', 'like', '%' . $request['name'] . '%')
                    ->whereHas('roles', function ($query) {
                          $query->where('role_id','1');
                       })
                    ->take(5)->get();
 

Chciałbym natomiast, żeby zwracało mi również dane kiedy string będzie zawierał w sobie obie kolumny oddzielone jakimś znakiem, np. spacją. Czyli np. JAN KOWAL.
Osiągnąłem kiedyś podobnyefekt pisząc ręcznie query z concatem:

WHERE CONCAT(IMIE, '  ', NAZWISKO) LIKE '%zmienna%'

Czy coś w tym stylu bo pisze teraz z palca.

Prawdopodobnie rozwiązał bym to w ten czy inny sposób samemu, jednak problem nie wydaje mi się być, aż tak unikatowy, żeby trzeba było pisać query ręcznie, jednak w necie nie widzę niestety informacji na ten tamat :P

1

To czego szukasz, to prawdopodobnie full text search.

Btw. zastanawiałeś się, co się stanie jak ktoś wpisze nazwisko + imie?

0

witajcie

0

Przeglądając z ciekawości swoje stare wątki trafiłem na ten i pomyślałem, że podzielę się tym jak rozwiązałem problem i ewentualnie ktoś podpowie na ile jest to wydaje i słuszne rozwiązanie :P

Rozwiązuje problem podany przez Desu czyli możemy wpisywać imię + nazwisko, nazwisko + imię, albo szukać po adresie email tylko użytkowników z przypisaną rolą Customer (dodawana automatycznie do wszystkich użytkowników, którzy zarejestrują się poprzez formularz na stronie głównej).

$name = '%'.trim($request->name).'%';
        
$users = User::Where(function ($query) use ($name) {
                    $query->whereRaw('CONCAT(name, " ", surname) LIKE "'.$name.'"')
                          ->orWhereRaw('CONCAT(surname, " ", name) LIKE "'.$name.'"')
                          ->orWhere('email', 'like', $name);
                })
                    ->whereHas('roles', function ($query) {
                            $query->where('name', 'user');
                        })
                    ->orderBy('surname')
                    ->limit(5)
                    ->get();                    

Rozwiązanie nieco uproszczone z oryginalnego żeby pokazać składnie gdyby ktoś chciał go użyć.
W oryginale odpytuje to AJAXem na keyup z inputa kiedy $name ma długość minimalnie 3 znaków z dodatkowymi warunkami wynikającymi z potrzeb aplikacji.

W Laravel 5.3 niby doszło wsparcie dla Full Text Search, jednak z tego co rozumiem potrzeba do tego wykorzystać jakieś usługi firm trzecich więc dla pojedynczego zapytania (w tej konkretnej aplikacji będzie tylko ten jeden serach na tej zasadzie) nie bawiłem się w takie rzeczy.

Użytkowników docelowo też nie będzie w dziesiątkach tysięcy, co najwyżej kilka tyś po długich miesiącach/latacch więc wydajność zgaduje będzie wystarczająca. Samo wyszukiwanie dostępne jest tylko dla administratorów więc przeważnie jedna osoba tylko będzie z tego korzystała na raz.

@Edit:
Zaseedowałem na szybko bazę na 50k wierszy i w Laraverze postawionym na najtańszym hostingu wyszukuje informacje tylko z lekkim lagiem, który jest spokojnie do zaakceptowania więc chyba całkiem spoko to działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1