1 Отредактировано Ярослав (16.08.2018 13:28:36)

Тема: Подсистема поиска. Оптимизация, улучшение

Здравствуйте, коллеги!
Особо на поиск не обращал внимание, но тут у клиентов появились новые менеджеры, которые засыпали меня заявками.
Суть в том, что при наборе в поисковой строке слова "Ручка" во всплывающей подсказке выводятся первыми не товары с данным словом в начале, а просто товары, содержащие данное слово в названии. У покупателя может сложится ложное впечатление, что товаров "Ручка" в ассортименте нет (хотя их несколько тысяч)
Интересно, что вывод товаров на странице поиска отличается от вывода во всплывающем окне.
Я перепробовал все типы поиска, но все равно свое основное предназначение - поиск наиболее подходящего товара, ни один не выполнил.
Может быть. кто то использовать сторонние сервисы поиска или делал оптимизацию?

Вот пример с демо сайта. Ищу платья, выходят босоножки.
https://yadi.sk/i/Iql5BPsr3aHDZi

2 Отредактировано Ярослав (19.03.2019 18:55:23)

Re: Подсистема поиска. Оптимизация, улучшение

Разобрался я в причине того, что результаты поиска в блоке поиска отличаются от страницы поиска)
Я думал, что поиск в блоке поиска делается механизмами модуля Search, но получается, что там свой код и категории ищутся вне зависимости от настроек модуля Search просто по %like%.

Я немного скорректировал searchlineapi.inc.php в блоке поиска. Теперь поиск в категориях идет в следующем порядке: like%, транслитерация like%, %like%, транслитерация %like%. Если на этапе есть вхождение, то далее поиск не идет. Слава богу, "мел" теперь найти можно))
https://yadi.sk/d/geI1drZ9g7ZIJg

И до кучи в контроллере блока searchline поменял порядок вывода: Категория->Товар->Бренд.
В принципе, клиент доволен, я тоже) Получается, что претензии были не к модулю поиска товаров, а к реализации поиска у блока строки поиска.

https://yadi.sk/d/rIjrrrzoKe3IqQ

Re: Подсистема поиска. Оптимизация, улучшение

Ярослав, а как посмотреть в действии Вашу доработку? Как ее подключить на сайте?

4

Re: Подсистема поиска. Оптимизация, улучшение

Алексей, ведь Ярослав скинул файл. Положите его рядом с оригинальным файлом
/modules/search/model/searchapi.inc.php
и всё

Re: Подсистема поиска. Оптимизация, улучшение

положил, но не особо разницу увидел. По трем символам не ищет вовсе. и вообще в выдаче много мусора как выдавало, так и выдает. В настройках какой должен быть поиск по умолчанию?

6 Отредактировано Ярослав (18.03.2019 13:33:51)

Re: Подсистема поиска. Оптимизация, улучшение

Кеш сбрасывали? Я корректировал только вывод категорий, так как он выводится не модулем поиска.
Мусор при выводе может быть из за того, что включен поиск в описании и характеристиках.

То есть решил задачу только для вывода категорий, вывод товаров надо настраивать в модуле поиска.

Re: Подсистема поиска. Оптимизация, улучшение

Ярослав пишет:

Кеш сбрасывали? Я корректировал только вывод категорий, так как он выводится не модулем поиска.
Мусор при выводе может быть из за того, что включен поиск в описании и характеристиках

На всякий случай сбросил. Но без изменений.

Re: Подсистема поиска. Оптимизация, улучшение

Ярослав пишет:

Разобрался я в причине того, что результаты поиска в блоке поиска отличаются от страницы поиска)
Я думал, что поиск в блоке поиска делается механизмами модуля Search, но получается, что там свой код и категории ищутся вне зависимости от настроек модуля Search просто по %like%.

Я немного скорректировал searchlineapi.inc.php в блоке поиска. Теперь поиск в категориях идет в следующем порядке: like%, транслитерация like%, %like%, транслитерация %like%. Если на этапе есть вхождение, то далее поиск не идет. Слава богу, "мел" теперь найти можно))
https://yadi.sk/d/geI1drZ9g7ZIJg

И до кучи в контроллере блока searchline поменял порядок вывода: Категория->Товар->Бренд.
В принципе, клиент доволен, я тоже) Получается, что претензии были не к модулю поиска товаров, а к реализации поиска у блока строки поиска.

Напишите пожелания в наш сервис пожеланий.

Re: Подсистема поиска. Оптимизация, улучшение

Хорошо, Александр, создам.

И до кучи в контроллере блока searchline поменял порядок вывода: Категория->Товар->Бренд.

Забыл модифицированный контроллер блока выложить https://yadi.sk/d/rIjrrrzoKe3IqQ
из catalog/controller/block

10

Re: Подсистема поиска. Оптимизация, улучшение

Ярослав пишет:

Хорошо, Александр, создам.
Забыл модифицированный контроллер блока выложить из catalog/controller/block

О! А вот так вроде другие результаты стали. Более релевантные. Еще потестирую.

11

Re: Подсистема поиска. Оптимизация, улучшение

https://helpdesk.readyscript.ru/wish/Mo … a-684.html
Добавил пожелание

12

Re: Подсистема поиска. Оптимизация, улучшение

1. почему после транслитерации запроса пропал setFilter('public', 1) ?
2. чем setFilter('name', "$query%", 'like') от setFilter('name', $query, '%like%') отличается? почему такой синтаксис?
3. удаление методов getSearchQueryProductResults, getSearchQueryProductCount ломает обратную совместимость и может привести к проблемам в сторонних модулях.

У меня получился вот такой вариант:

public function getSearchQueryCategoryResults($query, $limit = 1)
{
    $list = $this->dirapi
                 ->setFilter('name', $query, 'like%')
                 ->setFilter('public', 1)
                 ->getList(1, $limit);
    $limit -= count($list);
    
    if ($limit) {
        $list2 = $this->dirapi
                      ->clearFilter()
                      ->setFilter('id', $this->getIds($list), 'notin')
                      ->setFilter('name', $query, '%like%')
                      ->setFilter('public', 1)
                      ->getList(1, $limit);
        $list = array_merge($list, $list2);
        $limit -= count($list2);
    }
    
    // Если не нашли результаты, то посмотрим с транслитом
    if ($limit) {
        $query = Transliteration::puntoSwitchWord($query);
        $list2 = $this->dirapi
                      ->clearFilter()
                      ->setFilter('id', $this->getIds($list), 'notin')
                      ->setFilter('name', $query, 'like%')
                      ->setFilter('public', 1)
                      ->getList(1, $limit);
        $list = array_merge($list, $list2);
        $limit -= count($list2);
        
        if ($limit) {
            $list2 = $this->dirapi
                          ->clearFilter()
                          ->setFilter('id', $this->getIds($list), 'notin')
                          ->setFilter('name', $query, '%like%')
                          ->setFilter('public', 1)
                          ->getList(1, $limit);
            $list = array_merge($list, $list2);
        }
    }
    return $list;
}

Повысить оценку Понизить оценку

13 Отредактировано Ярослав (23.03.2019 02:37:27)

Re: Подсистема поиска. Оптимизация, улучшение

1. почему после транслитерации запроса пропал setFilter('public', 1) ?
2. чем setFilter('name', "$query%", 'like') от setFilter('name', $query, '%like%') отличается? почему такой синтаксис?
3. удаление методов getSearchQueryProductResults, getSearchQueryProductCount ломает обратную совместимость и может привести к проблемам в сторонних модулях.

1. В исходном коде этого не было
2. В исходном коде был первый вариант, я использовал второй.
3. Методов не хватает, так как делалось для старой версии 3, там их нет.

14

Re: Подсистема поиска. Оптимизация, улучшение

 /**
     * Возвращает результаты поиска по категориям в зависимости от запроса
     *
     * @param string $query - строка для поиска
     * @param integer $limit - лимит результатов поиска
     *
     * @return \Catalog\Model\Orm\Dir[]
     */
    function getSearchQueryCategoryResults($query, $limit = 1)
    {
        $list = $this->dirapi->setFilter('name', "%$query%",'like')
            ->getList(1, $limit);

        //Если не нашли результаты, то посмотрим странслитом
        if (empty($list)){
            $query = \RS\Helper\Transliteration::puntoSwitchWord($query);
            $list = $this->dirapi->clearFilter()->setFilter('name', "%$query%",'like')
                ->getList(1, $limit);
        }
        return $list;
    }

Вот код исходного модуля. О public речи нет.

15

Re: Подсистема поиска. Оптимизация, улучшение

    /**
     * Возвращает результаты поиска по категориям в зависимости от запроса
     *
     * @param string $query - строка для поиска
     * @param integer $limit - лимит результатов поиска
     *
     * @return \Catalog\Model\Orm\Dir[]
     */
    function getSearchQueryCategoryResults($query, $limit = 1)
    {
        $list = $this->dirapi
                        ->setFilter('name', $query, '%like%')
                        ->setFilter('public', 1)
                        ->getList(1, $limit);

        //Если не нашли результаты, то посмотрим странслитом
        if (empty($list)){
            $query = Transliteration::puntoSwitchWord($query);
            $list = $this->dirapi->clearFilter()->setFilter('name', "%$query%",'like')
                ->getList(1, $limit);
        }
        return $list;
    }

В версии на текущую дату public есть, но нет его в транслитерации. Забыли видимо

16

Re: Подсистема поиска. Оптимизация, улучшение

Ярослав пишет:

В версии на текущую дату public есть, но нет его в транслитерации. Забыли видимо

о каком public'е Вы все пишите?

Ярослав пишет:

1. В исходном коде этого не было

качественно перенесли старые баги!

Ярослав пишет:

3. Методов не хватает, так как делалось для старой версии 3, там их нет.

Вы бы хоть написали об этом, а то кто-то на радостях скачает и радости не ощутит smile

Повысить оценку −3 Понизить оценку

17 Отредактировано Ярослав (23.03.2019 04:26:46)

Re: Подсистема поиска. Оптимизация, улучшение

о каком public'е Вы все пишите?

качественно перенесли старые баги!

Вы бы хоть написали об этом, а то кто-то на радостях скачает и радости не ощутит smile

Мне уже начинает надоедать ваша манера общения. Кто хочет, тот применит, если надо исправит. Какой public понятно из пункта 1 вашего же вопроса.

18

Re: Подсистема поиска. Оптимизация, улучшение

Опять мучаю стандартный поиск
Вопрос к разработчикам. Заметил, что при любом типе поиска сортировка слетает, так как контроллер ListProducts в 247
просто устанавливает свою сортировку. Это неправильно! При полнотекстовом поиске, например, идет сортировка по релевантности, а она сбрасывается на сортировку по-умолчанию.
Может быть не устанавливать сортировку при наличии запроса на поиск и неустановленной принудительной сортировке? Пока просто перенес установку сортировки:

//Устанавливаем сортировку
                //$sort_field = $this->cur_sort == 'rank' ? $this->cur_sort : $this->api->defAlias().'.'.$this->cur_sort;
                //$this->api->setSortOrder($sort_field, $this->cur_n_sort);
                
                if (!empty($this->query) && $dir == 0) { //Если это результат поиска, 
                    $sub_dirs = $this->api->getDirList(); //Загружаем список категорий, в которых найдены товары
                } else {
                   //eventus
                    $sort_field = $this->cur_sort == 'rank' ? $this->cur_sort : $this->api->defAlias().'.'.$this->cur_sort;
                    $this->api->setSortOrder($sort_field, $this->cur_n_sort);
                
                    //Загружаем список подактегорий, у текущей категории
                    $this->dirapi->setFilter('parent', $dir_id);      
                    $this->dirapi->setFilter('public', 1);
                    $sub_dirs = $this->dirapi->getList();
                }

Стоит сортировка по-умолчанию по дате создания товара.
Было в результатах поиска:

Подставка для шоколада
...куча другого товара с шоколадом в 20-й позиции
Шоколад такой то

Стало:

Шоколад такой то
Подставка для шоколада
...куча другого товара с шоколадом в 20-й позиции

Сортировка order by RANK просто напросто игнорируется в стандартном коде. Или я чего то не понимаю.

p.s.
Кстати, для поиска like можно добавить сортировку через LOCATE, тогда результаты замечательно сортируются по вхождению строки:

ORDER BY LOCATE('шоколад',B.`title`)

19

Re: Подсистема поиска. Оптимизация, улучшение

Разобрался. У вас ошибка в коде в 66 строке

  $this->search_type = ConfigLoader::byModule('search')->searchtype;

Вместо searchtype надо search_type,

  $this->search_type = ConfigLoader::byModule('search')->search_type;

И еще с 3 версии сортировка по релевантности не работает. (((((((((((((((((((((((
Я и смотрю, запрос, сформированный модулем поиск  великолепно выводит данные, а товары на сайте непонятно как выведены.

Re: Подсистема поиска. Оптимизация, улучшение

Напишите пожалуйста в поддержку.

21 Отредактировано Ярослав (25.09.2019 11:44:33)

Re: Подсистема поиска. Оптимизация, улучшение

Александр, написал.
Все сайты на техподдержке исправил, теперь просто конфетка, а не поиск

22

Re: Подсистема поиска. Оптимизация, улучшение

Здравствуйте, Ярослав.
Продемонстрируйте конечный код если возможно.

Повысить оценку Понизить оценку

23

Re: Подсистема поиска. Оптимизация, улучшение

Андрей пишет:

Здравствуйте, Ярослав.
Продемонстрируйте конечный код если возможно.

В файле /catalog/contrloller/fron/listproducts.inc.php примерно в 66 строке идет присваивание переменной текущей настройки  модуля поиска.

 $this->search_type = ConfigLoader::byModule('search')->searchtype;

Надо добавить символ подчеркивания _:

 $this->search_type = ConfigLoader::byModule('search')->search_type;

24

Re: Подсистема поиска. Оптимизация, улучшение

Благодарю, Ярослав

Повысить оценку Понизить оценку

25

Re: Подсистема поиска. Оптимизация, улучшение

Перестал производится полнотекстовый поиск по 4 символам. Хотя в настройках mysql минимальная длина слова стоит вообще 3.
Оказывается, в обновлениях RS

  protected function getStemmedQuery()
    {
        //Если в поисковой строке найдены кавычки,
        //не применяем эвристических методов улучшения результатов.
        //Считаем, что пользователь опытный, сам составляет запрос.
        if (strpos($this->query, "\"") !== false) return $this->query;
        
        
        $words = preg_split('/[\s,]+/u', $this->query, -1, PREG_SPLIT_NO_EMPTY);
        $stemmer = new \Search\Model\Stem\Ru();
        
        $query = $this->query;
        foreach($words as $word) {
            //Если перед словом не будет задан спец-символ, ставим + (слово обязательно должно присутствовать в результате)
            if (!preg_match('/[+\-"~(<>]/', mb_substr($word,0,1))) {
                $query = str_replace($word, '+'.$word, $query);
            }
            
            $stemmed = $stemmer->stemWord($word);
            if (mb_strlen($stemmed)>3) {//Если после стеминга слово не стало менее 4-х символов, то 
                $query = str_replace($word, $stemmed.'*', $query);
            }
        }

        return $query;
    }

Ранее было

 if (mb_strlen($stemmed)>2) {//Если после стеминга слово не стало менее 4-х символов, то 
                $query = str_replace($word, $stemmed.'*', $query);
            }

Стало:

 if (mb_strlen($stemmed)>3) {//Если после стеминга слово не стало менее 4-х символов, то 
                $query = str_replace($word, $stemmed.'*', $query);
            }

Пришлось скорректировать обратно. Поиск с 3-х букв заработал.
Я не пойму, почему даже по 4 не искало, только с 5, а сейчас с 3-х находит.
Хорошо бы в настройки вывести, потому как при маленькой базе и с 2-х символов искать можно.