Помощ с едно 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 - винаги я показва, нищо че е зададен друг град, категория, цена и тип. <= това е грешното поведение
 
Последно редактирано:
Добре, това нещо ми загуби 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
 
Само като видя LIKE вместо Full Text search и ми става ясно, че спасение няма :).

Ползваш Laravel query builder да направиш заявка, нали така? Или бъркам, че искаш Ларавел да ти замести мисловният процес?
 
Само като видя LIKE вместо Full Text search и ми става ясно, че спасение няма :).

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

Сподели твоето 200IQ решение на optimal search
 
Само като видя LIKE вместо Full Text search и ми става ясно, че спасение няма .

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

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

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

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

Горе