Помощ с едно Laravel Query - search с оптимални параметри

ReminD

Well-Known Member
Привет, може ли едно рамо с Laravel query. Нещо не ми се получават нещата по ларавелския начин, ако някой може да хвърли едно око, защото query-то ми се вижда legit, но не работи както трябва.

Идеята е search с optimal parameters. Търсене по title и description работи коректно, тоест вади резултати, но real case : потребителя решава да търси keyword в различна категория или да филтрира цена / друга категория/ тип и т.н.. -> какво трябва да се случва тогава -> да не показва резултата от намерените Ads по title / description.


Приемете, че данните идват от request и са валидни id-та.
PHP:
        $result = Ad::when($keyword, function ($q) use ($keyword) {

           return $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');

        })

            ->when($category_id, function ($q) use ($category_id) {

               return $q->where('category_id', $category_id);

            })

            ->when($region_id, function ($q) use ($region_id) {

                return $q->where('region_id', '=', $region_id);

          })

           ->when($type_id, function ($q) use ($type_id) {

                return $q->where('adtype_id', '=', $type_id);
           })

          ->when($min_price, function ($q) use ($min_price) {

              return $q->where('price', '>=', $min_price);

            })

           ->when($max_price, function ($q) use ($max_price) {

               return $q->where('price', '<=', $max_price);

           })

           ->paginate(8);

Другият, вариант, който си е Laravel Way, с релациите, е този, който също не работи коректно, намира обяви по title/ description, и ги показва, дори когато е зададена друга категория

PHP:
$result = Ad::when($keyword, function ($q) use ($keyword) {
        return $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');
    })
        ->whereHas('category', function ($q) use ($category_id) {
            return $q->where('category_id', $category_id);
         })
        ->whereHas('region', function ($q) use ($region_id) {
            return $q->where('region_id',  $region_id);
        })
        ->whereHas('type', function ($q) use ($type_id) {
            return $q->where('adtype_id',  $type_id);
        })
        ->where('price', '>=', $min_price)
        ->where('price', '<=', $max_price)
        ->paginate(8);


        return view('search.index', compact('result'));


}

Третият ми вариант е с Filters, което май ми се вижда най-удачно, накрая май натам ще се ориентирам, ако не успея да подкарам това нещо. Четвърти вариант е с if проверки какво има в $request-a, но ще стане мноого грозно с доста проверки и не ми се иска да е така.

Къде изпускам и какво? Thanks. In the end - ако обявата е намерена по title/ description - винаги я показва, нищо че е зададен друг град, категория, цена и тип. <= това е грешното поведение
 
Последно редактирано:

ReminD

Well-Known Member
Добре, това нещо ми загуби 10 часа, пускане на въпрос в стаковърфлов, никакъв резултат от там, а какъв бил проблема

Ей това старото не работи
PHP:
$result = Ad::when($keyword, function ($q) use ($keyword) {
            return $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');
        })
            ->when($category_id, function ($q) use ($category_id) {
                return $q->where('category_id', $category_id);
            })
            ->when($region_id, function ($q) use ($region_id) {
                return $q->where('region_id', '=', $region_id);
            })
            ->when($type_id, function ($q) use ($type_id) {
                return $q->where('adtype_id', '=', $type_id);
            })
            ->when($min_price, function ($q) use ($min_price) {
                return $q->where('price', '>=', $min_price);
            })
            ->when($max_price, function ($q) use ($max_price) {
                return $q->where('price', '<=', $max_price);
            })
            ->paginate(8);
Така работи

PHP:
$result = Ad::when($keyword, function ($q) use ($keyword) {
            return $q->where(function($q) use ($keyword) {
                $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');
            });
        })
            ->when($category_id, function ($q) use ($category_id) {
                return $q->where('category_id', $category_id);
            })
            ->when($region_id, function ($q) use ($region_id) {
                return $q->where('region_id', '=', $region_id);
            })
            ->when($type_id, function ($q) use ($type_id) {
                return $q->where('adtype_id', '=', $type_id);
            })
            ->when($min_price, function ($q) use ($min_price) {
                return $q->where('price', '>=', $min_price);
            })
            ->when($max_price, function ($q) use ($max_price) {
                return $q->where('price', '<=', $max_price);
            })
            ->paginate(3);
Така работи, заради WHEN:: в шибаното query в началото, трябва да wrapne в group-а... no comment
 

AMitrev

Well-Known Member
Само като видя LIKE вместо Full Text search и ми става ясно, че спасение няма :).

Ползваш Laravel query builder да направиш заявка, нали така? Или бъркам, че искаш Ларавел да ти замести мисловният процес?
 

ReminD

Well-Known Member
Само като видя LIKE вместо Full Text search и ми става ясно, че спасение няма :).

Ползваш Laravel query builder да направиш заявка, нали така? Или бъркам, че искаш Ларавел да ти замести мисловният процес?
Сподели твоето 200IQ решение на optimal search
 

Станимир И

Active Member
Само като видя LIKE вместо Full Text search и ми става ясно, че спасение няма .

Ползваш Laravel query builder да направиш заявка, нали така? Или бъркам, че искаш Ларавел да ти замести мисловният процес?
Привет, нищо към автора и темата, мислех да не пиша тук но си прав, конкренто скоро ни се наложи да пишем сериозна търсачка за 3 милиона продукта, ползвахме ElasticSearch, разбрахме че LIKE е доста нефективен метод. В най-лошия случай моделът LIKE ще има водещи заместващи символи, които изискват да се изследва всеки индексен ключ, което се сещаш че ще стане доста проблемно при голям обем на товар и запитвания.

Докато Full-text
  • лексикален анализ - разбиване на блок от неструктуриран текст на отделни думи, фрази и специални символи(искам маса метал) веднага ще се селектират масите от метал, доста умно!
  • морфологичен анализ или произтичащи - свиване на вариации на дадена дума в един индексен термин; например, третиране на "чанти" и "чанта", или "стол" и "столове" като една и съща дума което ще спести не намерени резултати.
Има още доста но нямам време да пиша тук :)

Поздрави,
Станимир
 

onlinewebbg

New Member
За мен е много по-лесно с чист sql - колкото и да хвалят тези query bildery, много по-лесно и разбрано ми е по другия начин.
 

hristonev

Active Member
За мен е много по-лесно с чист sql - колкото и да хвалят тези query bildery, много по-лесно и разбрано ми е по другия начин.
То с всички е така. ОРМ-а не ти прави живота по-лесен, а те пази от лошите батки, де дебнат в тъмното :cool:
 

Горе