Некорректно работает поиск товаров

Первый кейс:

Есть 5 товаров, в названии которых первое слово Монголия.

При вводе в поисковое окошко слова "монголия", "монго" и т.п. выдается только 3 товара. Если вводить "онголия", выдаются все пять.

Товары созданы в бэкенде руками. Индекс пересобран. В бэкенде результаты поиска такие же.

Второй кейс: не ищет по тегу 1812. Один товар выдается, но там это число есть в названии. Второй товар не выдается.

21 ответ

  • 2

    По первому - я так подозреваю, что если искать "Монго", то товар найдется ?
    Посмотрите что у вас указано в БД. Таблица shop_search_word параметр Collation.
    По идее он должен быть utf8_general_ci, если не так, то поправьте(скорее всего у вас выбран регистрозависимый collations)

    По второму - если включен "умный" поиск, то попробуйте увеличить коэфициент для тэгов. Если выключен, то он по тегам и не будет искать...но судя по фразе "Индекс пересобран" - используете "умный".


    • +1
      IgorG IgorG 5 декабря 2016 19:02 #

      По второму кейсу помогло, спасибо.

      По первому - нет. Монго точно так же не работает. В таблицы поэтому залезать не стал :).

      Может быть, еще какие-то варианты есть?

      Могу добавить, что этот товар я делал через дубликат + генератор ЧПУ.

      • +2

        Возможно английская "М" ? -) Либо какой-то нечитаемый символ...
        Попробуйте руками изменить и еще раз индексацию сделать.

        • +1
          IgorG IgorG 5 декабря 2016 19:58 #

          дело точно не в этом, т.к. это я проделал до обращения сюда

          • +2

            Если не в облаке, то в wa-apps/shop/lib/classes/shopProductsCollection.class.php
            Метод public function getSQL()
            Перед return $sql воткните логирование запроса к базе
            waLog::log(var_export($sql, true), 'opaopa.log');
            и смотрите на запрос в логе wa-log/opaopa.log
            Взять этот запрос и исполнить самому в базе, чтобы посмотреть почему именно возвращается не то, что нужно.

            • +1
              IgorG IgorG 5 декабря 2016 21:50 #

              не в облаке.

              перестартовывать после замены файла что-то нужно и как?

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

              • +2

                Почистить кэш не помешает.
                Ну и возможно я ошибся...смотрел быстро и "по верхам", глубоко не вникая. Но вроде как getSQL всё-таки вызывается при поиске.

                Что нужно. Протрассировать цепочку вызовов в этом классе и выцепить итоговый запрос.
                Как вариант поделать простые запросы к shop_search_word и shop_search_index и посмотреть выдадут ли они нужный продукты по запросу "Монго". Провести исследование по различным вариантам запросов.
                Сделать селект на сам "проблемный" продукт и посмотреть в каком виде это имя в базе...в общем искать причину.
                То есть проблема либо в поисковом индексе, либо в самом продукте.

                • +1
                  IgorG IgorG 5 декабря 2016 22:19 #

                  идея мне понятна, но боюсь, что без конкретных инструкций типа "написать там вот это" я не справлюсь, т.к. кроме нотепада и тоталкоммандера у меня ничего нет, да и пхп я не знаю.

                  • +1
                    IgorG IgorG 5 декабря 2016 22:59 #

                    еще один момент заметил: когда в бэкенде пишу в поиске товаров Монго... выдаются в выпадающем списке все 5 Монголий. Даже по 2 раза, т.к. еще в кратком описании это слово есть. После нажатия ентера в результатах поиска остается 3 товара

  • 1
    IgorG 6 декабря 2016 08:58 #

    это да.

    Проблема в том, что новые товары тоже не ищутся

  • 1
    IgorG 6 декабря 2016 14:03 #

    это уже установлено было. Дело не в этом

  • 1
    IgorG 6 декабря 2016 14:35 #

    дополнение: простой поиск ищет правильно, по "монго" выдается все 5 товаров. После включения умного поиска опять 3 товара.

  • 2

    В общем проблема оказалась многоступенчатой.

    Всё начинается с "кривого" названия товара и других текстовых параметров по которым строится индекс.
    Например "Совершенство" - на первый взгляд нормальное слово в кавычках. Но впереди, конечно же что-то из этого списка.

    При сохранении товара происходит апдейт поисковых индексов. При сохранении слов в индексе( shopIndexSearch->addToIndex() ) происходит только трансформация к нижнему регистру. Слово записывается как есть, с нечитаемым, но вполне реальным символом спереди.

    Далее поиск. Умный.
    Сначала идёт поиск по индексу.
    shopSearchWordModel->getIds()
    тут конструкция вида

    $where[] = "name LIKE '".$this->escape($w, 'like').($by_part && mb_strlen($w) >= $by_part ? '%' : '')."'";

    как видно, LIKE без начального % - то есть поиск с начала слова, в принципе логично(это кстати один из вариантов решения - делать поиск по '%слово%', а не 'слово%').
    Так как поиск только с начала слова, а не LIKE "%слово%", то конечно же проблемное слово в этот запрос не попадает.
    Но у нас есть еще тысячи товаров и там есть слово "совершенство". Нормальное.Таким образом поиск какие-то товары в индексе находит.

    Далее.
    В shopProductCollection->searchPrepare() есть условие - если ничего не найдено на предыдущем шаге

    if(!$this->count())

    , то тогда производится доп.поиск по имени товара или названию артикула. По сути - дублирование простого поиска. Но в нашем случае что-то выдалось, простой поиск не подключался и в выдаче нужного товара нет.

    С этой вакханалией надо кончать - как показывает практика, проблем с этими символами очень много. Просто все закрывают глаза и переключают на простой поиск.

    Варианты решений:
    1.выкусывание не читаемых пробелов и других подобных символов при сохранении в индекс
    2. поиск в индексе по шаблону %слово%

    Первый конечно же предпочтительней.

    P.S. Дайте мне пирожок...заколебался я эту фигню расковыривать -(

  • 1
    IgorG 6 декабря 2016 20:46 #

    спасибо за подробный разбор проблемы. Я правильно понимаю, что можно в исходном коде добавить % в правильном месте и все?

    По первому варианту проблемы непонятно, как там появился нечитаемый символ. Я товар создавал через админку. Как эти символы выкусывать?

  • 3

    Да. Временное решение в wa-apps/shop/lib/model/shopSearchWord.model.php вместо LIKE '".$this сделать LIKE '%".$this

    public function getIds($words, $by_part = 0)
        {
            $where = array();
            foreach ($words as $w) {
                $w = trim($w);
                if ($w) {
                    $w = shopSearch::stem($w);
                    $where[] = "name LIKE '%".$this->escape($w, 'like').($by_part && mb_strlen($w) >= $by_part ? '%' : '')."'";
                }
            }
            if ($where) {
                $sql = "SELECT id FROM ".$this->table." WHERE ".implode(' OR ', $where);
                return $this->query($sql)->fetchAll(null, true);
            }
            return array();
        }


    Про выкусывание и прочее - это для разрабочиков webasyst писал.

    А символы берутся из копи-пасты, прайсов поставщиков и других мест. Сами по себе они не возникают.

  • 1
    IgorG 7 декабря 2016 00:57 #

    Немного вас расстрою :)

    Поправил файл. Монголия как не искалась, так и не ищется (опять выдается 3 из 5 товара). Раньше онголия искала все. Теперь онголия, нголия тоже выдает 3 товара. голия выдает все 5.

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

    Еще я обратил внимание на то, что товары, которые выдаются, содержат еще раз слово Монгольская в названии. Остальные не содержат. Похоже, действительно первая буква странно отрабатывает, но синтаксис LIKE '%xxx%' от этого не спасает. Подзабыл сиквел немного. Подскажите, а знак процента отсутствие букв допускает или любое количество букв больше равно одной?

    • +2

      1.Проверьте, что этот товар по слову "монголия" точно есть в индексе.
      в моём случае вот что выводится

      mysql> SELECT * FROM shop_search_word s1 LEFT JOIN shop_search_index s2 ON s1.id = s2.word_id WHERE s1.name LIKE '%совершенство%';
      +------+-----------------------------+---------+------------+--------+
      | id   | name                        | word_id | product_id | weight |
      +------+-----------------------------+---------+------------+--------+
      | 1001 | совершенство                |    1001 |         37 |     60 |
      | 1001 | совершенство                |    1001 |        153 |     60 |
      | 1001 | совершенство                |    1001 |        219 |     60 |
      | 1001 | совершенство                |    1001 |        411 |     60 |
      | 7246 | совершенство               |    7246 |        502 |    100 |
      +------+-----------------------------+---------+------------+--------+
      5 rows in set (0,01 sec)
      

      нужный мне товар это product_id = 502. Видите у него правая палочка в поле name сдвинута на символ? Это как раз сигнал о невидимом символе в начале.

      и по запросу 'слово%' - он не найдётся

      mysql> SELECT * FROM shop_search_word s1 LEFT JOIN shop_search_index s2 ON s1.id = s2.word_id WHERE s1.name LIKE 'совершенство%';
      +------+--------------------------+---------+------------+--------+
      | id   | name                     | word_id | product_id | weight |
      +------+--------------------------+---------+------------+--------+
      | 1001 | совершенство             |    1001 |         37 |     60 |
      | 1001 | совершенство             |    1001 |        153 |     60 |
      | 1001 | совершенство             |    1001 |        219 |     60 |
      | 1001 | совершенство             |    1001 |        411 |     60 |
      +------+--------------------------+---------+------------+--------+
      4 rows in set (0,00 sec)
      

      2. Увеличьте коэф. у названия до 100 и сделайте переиндексацию.

      3. Чистите кэш.

Добавить ответ

Чтобы добавить комментарий, зарегистрируйтесь или войдите