Полнотекстовый поиск по сайту — бич современного интернета

    Реализация хорошего поиска по сайту — часто сильно недооцененная по сложности задача. Поиск является слабым местом сайтов настолько часто, что когда я вижу строку поиска, у меня сразу же возникает предвзятое ощущение предстоящего фиаско. И чтобы лишний раз не расстраиваться, я сразу переадресую свой вопрос гуглу или яндексу и быстро нахожу то, что требовалось. Что же делать, чтобы как-то улучшить эту ситуацию?

    Форма поиска по сайту от Яндекса и Гугла 


    Лучше всего это поняли и сделали за нас создатели популярных поисковых систем. И мы можем воспользоваться результатами их трудов, просто установив форму поиска по сайту от Яндекса или Гугла.Это простой путь, но у него есть свои минусы:
    1. В поиске могут быть доступны не все страницы сайта. Поисковая система не гарантирует включения в поиск всех страниц сайта, а кроме того не все страницы могут быть доступны поисковому роботу.
    2. Большая задержка между появлением новых страниц на сайте и их доступностью в поиске.
    3. Нельзя задавать уточнения для поиска. Например, задать поиск только в одном подразделе сайта или по ценовому диапазону товара.
    4. Нельзя идеально встроить результаты поиска в дизайн сайта. Это перечеркивает все плюсы такого поиска для большинства солидных порталов.
    Вот неполный перечень проблем, с которыми может столкнуться начинающий поисковод. Поэтому такое решение можно рекомендовать только сайтам, не особо беспокоящимся о своём коммерческом имидже.

    Качество поиска 


    Для начала нужно понять, из чего вообще складывается понятие качества поиска.  Качество поиска зависит от многих факторов. О многих из них можно прочитать в книге известного поискового оптимизатора кандидата технических наук Игоря Ашманова. (Скажу по секрету, что недавно видел её на torrents.ru). Все факторы условно можно разбить на три категории: полнота, точность и ранжирование. 

    Полнота 


    Полнота — это количество страниц, по которым выполняется поиск. Существует два подхода к индексированию данных для поиска: «изнутри» и «снаружи».
    1. «Изнутри» — это индексирование исходных данных сайта, обычно хранящихся в БД. Этот способ исключает попадание в результаты поиска «мусорных» страниц, но и связан с риском уменьшения полноты поиска.
    2. «Снаружи» — индексирование поисковым роботом. Этот подход в большинстве случаев гарантирует высокую полноту, но и порождает множество проблем, которые будут описаны в будущих статьях.
    Если пользователь видит на сайте поисковую строку без сопроводительного текста, то он ожидает, что, введя запрос «контакты», он попадет на страницу контактов. А если это не так, то это ошибка вебмастера, потому что клиент всегда прав :)

    Причина этого чаще всего в том, что на большинстве сайтов реализован поиск только по динамическим данным из-за того, что поисковая программа получает данные из базы данных. Более того, обычно вебмастер (или создатель CMS) решает, какие таблицы в БД самые важные, а какие недостойны внимания. В результате «за бортом» поиска остаются некоторые «малозначимые» динамические данные и все статические страницы.

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

    Точность 


    Точность поиска — это характеристика соответствия найденных страниц поисковому запросу. В неё входят учет морфологии, снятие омонимии, учет опечаток, поиск по синонимам и др. Например, если пользователь ищет «количество голов Аршавина», то ясно, что головы тут ни при чем, и нужно показывать только информацию про забитые голы. Вот еще один интересный пример омонимии. Но это высший пилотаж, а самое простое, что хочет увидеть пользователь — это поиск по всем возможным словоформам.

    Для учета морфологии используются различные алгоритмы: стеммеры, морфологические словари и гибридные алгоритмы. Все они в той или иной степени  несовершенны. Например, слово «есть» может иметь формы «был», «будет», «ем». Простой стеммер этого не поймёт. Морфологический словарь вряд ли предоставит словоформы для слова «упячка». Более сложные гибридные алгоритмы, использующие словарные базы и наборы эвристик, более совершенны, но и они неидеальны.  Сейчас ситуация с учетом морфологии примерно такая:
    1. При поиске по БД только лишь средствами SQL обычно используют стеммер. Это наихудший учет морфологии
    2. Open source поисковые системы, такие как Sphinx, Lucene, Xapian обычно поддерживают установку своего морфологического анализатора, но в качестве встроенного алгоритма для русского языка обычно также используется стеммер. 
    3. Яндекс.СерверFAST, Google Appliance имеют продвинутые гибридные алгоритмы учета морфологии. Вероятно, Яндекс.Сервер и  Google Appliance  имеют наилучший морфологический анализатор для русского языка из существующих, так как они используют тот же алгоритм, что и в веб-поиске. 


    Ранжирование


    Под ранжированием понимается порядок сортировки найденных документах на странице результатов поиска. Иногда достаточно сортировать результаты по простому критерию, например, по дате модификации, но чаще всего требуется упорядочивание документов в порядке уменьшения близости поискового запроса результату. На ранжировании разработчики крупных поисковых систем сломали много копий, поэтому их продукты дают наилучшие результаты. Ситуация с ранжированием примерно такая:
    1. При использовании поиска средствами SQL доступно ранжирование только по простым критериям, таким как дата. 
    2. Open Source системы (Sphinx, Lucene, др.) имеют встроенные продвинутые алогритмы ранжирования. Обычно это модификации алогритма текстовой релевантности.
    3. Коммерческие продукты (Яндекс.Сервер, FAST, Google Appliance, др.) имеют сложные многофакторные алгоритмы ранжирования, секрет которых хранится в тайне под семью замками так же, как рецепт приготовления Кока-Колы.

    Выводы 

    1. Для небольшого некоммерческого сайта подойдет форма поиска Яндекса/Гугла.
    2. Для поиска по разделу сайта, не требующего анализа морфологии запроса, сложного ранжирования и содержащего небольшое количество данных, можно использовать SQL запрос + стеммер.  
    3. Для достаточно большого сайта, содержащего нетривиальные статьи стоит использовать движок с хорошей морфологией и ранжированием:Яндекс.Сервер, FAST, Google Appliance, др. 
    4. Lucene, Sphinx, и др. подойдут, если душа лежит к Open Source и требования к поиску удовлетворяются возможностями движка.

    Ссылки по теме

    1. «Обзор решений для полнотекстового поиска в веб-проектах: Sphinx, Apache Lucene, Xapian» — статья на http://www.developers.org.ua
    2. «High Performance FullText Search» — сравнение производительности поиска и индексации популярных полнотекстовых Open Source движков при работе с MySQL (PDF 109кб)  
    3. http://poiskovod.ru — оригинал статьи в моем блоге
    Поделиться публикацией

    Похожие публикации

    Комментарии 57
    • НЛО прилетело и опубликовало эту надпись здесь
        +3
        Может кто напишет, за что? :)
          +3
          Хабралюди восприняли это как спам и не совсем по теме статьи.
          Хотя регистронезависимый юникодный поиск — это задача, которую до сих пор не могут полностью решить в крупных поисковиках. Существуют языки, в которых очень сложно построить автомат, выполняющий конвертацию между регистрами букв.
        • НЛО прилетело и опубликовало эту надпись здесь
            +2
            И стадо дружно ставит плюсы, дабы доказать что оно не стадо, дружно ставящее минус.
            • НЛО прилетело и опубликовало эту надпись здесь
              0
              Есть зеленый плюс, нажму ))
            +1
            Вообще боюсь браться за решение подобных задач.
            У текущих CMS движков поиск тоже обычно реализован на достаточно низком уровне, что удручает ситуацию.
              +1
              Мне кажется, у вас лишнее слово в комментарии. 'удручает ситуацию' — звучит странно, без обид.
              И да, присоединюсь — с поиском в большинстве цмс, особливо бесплатных — неахти.
              • НЛО прилетело и опубликовало эту надпись здесь
                  0
                  Понятия не взаимоисключаеющие:))
                    0
                    «на» — предлог
                    «настолько» — наречие
                    +6
                    да ладно вам, кто из нас в юности не любил поудручать временами ))).
                  0
                  Я бы посоветовал интересующимся качественным SQL-поиском посмотреть доклад Олега Бартунова «Полнотекстовый поиск в PostgreSQL» на РИТ2007
                    0
                    «полнота и точность и ранжирование»
                    Что-то тут не так, запятые надо
                    +1
                    Очень хорошо всё расписано, но как-то никаких новых мыслей так и не появилось. Google|Яндекс ищёт лучше, но имеют кучу проблем — по бритве Оккама это лучше статьи. Но я как понимаю, это только введение, а дальше нас ждёт более интересные статьи :).
                      0
                      Очень хотелось бы, чтобы это было так!
                      Я уже так устал пробовать все новое и новое в проблеме поиска…
                      0
                      При использовании поиска средствами SQL доступно ранжирование только по простым критериям, таким как дата.
                      =====
                      Откуда просто дата? А как же match against? Или сортировка по сумме like'ов? :)
                        0
                        да лайками вроде бы как не выход. А что если будет очень-очень много записей в БД, а мы по ними лайками%). Это же тормоза будут и еще какие. Можно просто составить словарь из записей и оперировать релевантностью.
                          0
                          Лайк по словарю, в префиксном варианте очень даже ищет :)
                          Можно суммировать и match against в булевом режиме.
                          0
                          Поддерживаю, MATCH AGAINST вполне себе хорошо и быстро работает, релевантность очень даже релевантная получается в выдаче :)
                          0
                          >Нельзя задавать уточнения для поиска. Например, задать поиск только в одном подразделе сайта.
                          Ну вообще-то это только у Яндекса нельзя, у Гугла можно, так и называется — «уточнения» :)
                          +1
                          «Нельзя идеально встроить результаты поиска в дизайн сайта.»
                          xml.yandex.ru/
                          только для работы нужен отдельный айпи.
                            0
                            Например, «студент inurl:/News/?id=»
                              0
                              Нужно хорошо понимать, что стоит за api яндекса и других поисковиков. Никто не будет отдавать результаты поиска просто так, потому что имеются сложности монетизации. Поэтому Яндекс либо ограничивает количество разрешенных запросов в день, либо требует установки директа на поисковой выдаче, как в qip.ru & nigma.ru
                                +1
                                в день 1000 запросов для среднего сайта хватит на ура. qip и nigma это уже совсем другие проблемы и решения.
                              0
                              в тайне под семью замками так же, как рецепт приготовления Кока-Колы


                              рецепт кока-колы открыли уж несколько месяцев как.
                                0
                                считай, что статья написана несколько месяцев как.
                                +1
                                Бытует мнение, что хороший сайт должен иметь свой поиск. Вы заказчикам расскажите что поиск на сайте будет через яндекс :-) Их эта идея не вдохновит, уверяю вас.

                                Поиск часто бывает специализированным, т.е. с дополнительные параметрами, а вот про это вы не слова не сказали. И тут поисковикам делать нечего совершенно. А как правило именно такой поиск и бывает действительно нужен. Что же касается поисковых систем, то вы сначала должны как-то прийти на этот сайт, а вот это уже задача последних.

                                Вобщем, вы все правильно изложили, но только тогда когда у нас сайты состоят только из набора статических страниц или статей.
                                  0
                                  > # Нельзя задавать уточнения для поиска. Например, задать поиск только в одном подразделе сайта.

                                  Невнимательно читаете, если я правильно понял ваш комментарий.
                                    +1
                                    Да, не очень внимательно прочитал. Но тем неменее мысль остается — в большинетве случаев поиск или нужен с дополнительными параметрами или не нужен вообще ибо как вы правильно высказались он тутже прямиком из яндекса приводит туда куда нужно.
                                      0
                                      Эх, совсем не внимательно читаете — это не я высказывался:)
                                  +1
                                  Беда в том, что заказчик обычно воспринимает поиск, как дешевую фичу. Типа вообще почему она не идет бесплатно «до кучи»?

                                  Все потому, что формально эта строчка есть во всех ЦМС и во всех шаблонах с тимплейт-монстра.

                                  Некоторый относительно недорогой вариант дает использование Zend-Lucene (из фреймворка). Даже без стемминга результат вполне удовлетворяет заказчика (интерфейс для прикручивания русского стемминга есть, и видимо люди его прикручивают). Там конечно надо дописать пагинацию, например путем сохранения результатов поиска в сессии и постраничной выборки уже оттуда, т.к. готового механизма нет. Ну и обеспечить обновление индекса при работе с объектами каталога и пр.

                                    +1
                                    Совершенно с Вами согласен. Заказчик зачастую не может понять сложности реализации функции поиска, как ему не обьясняй. В результате разработчику приходится либо делать говнопоиск (под стать бюджету), либо делать хороший поиск при неадекватном бюджете, либо вообще отказываться от этой затеи.
                                    Как правило, разработчик выбирает вариант «говнопоиск».

                                    Я же в будущем в таких случаях буду просто идти в отказ, ибо говнопоиск делать не могу, а хороший поиск при неадекватном бюджете — не хочу (один раз пробовал — себе дороже).
                                    +1
                                    Обычно дешевле выполнить запрос заново, чем сохранять его в сессию. Это связано с тем, что поиск по инвертированному индексу выполняется очень быстро, а существенное время уходит на генерацию сниппетов.
                                      0
                                      всё верно — поиск по сайту, как это, может ни покажется странным — совсем нетривиальная задача — посмотрите на тот же livestreet.ru — у него встроен Sphinx, но ведь не у всех есть возможность договориться с хостером на его установку.
                                        0
                                        >«Нельзя идеально встроить результаты поиска в дизайн сайта.»
                                        Никаких проблем, ещё 4 года назад использовал xml поиск от yandex, надо только написать свой xsl шаблон
                                        xml.yandex.ru/

                                        В Google тоже не дураки работают
                                        www.google.com/sitesearch/#xml
                                          0
                                          Выше автор уже ответил на в точности такой же коммент :)
                                            0
                                            Гугловский поиск можно полностью подогнать под свой дизайн, тут http://habrahabr.ru/blogs/google/54012/ написано как
                                            0
                                            Я даже по хабру ищу через расширенную форму яндекса — «найти на сайте»
                                              0
                                              хотя на хабре не всё так плохо :)
                                                0
                                                Я бы сказал, что плохо все-таки ;(
                                                  0
                                                  собственный поиск хабра ужасен!
                                                  На хабре ищу только гуглом.
                                                  0
                                                  Но видеть на хабре встроенный поиск от яндекса или гугла я бы не хотел
                                                  +2
                                                  ИМХО, нормальный поиск по сайту начинается с анализа слов, которые вводятся в строку поиска САЙТА.
                                                  Потом берется этот анализ и разработчик интерфейса получает в лоб, если люди не могут найти очевидное.

                                                  Что касается полнотекстового поиска, то, имхо, на сайте он лишний — более эффективный поиск будет по словарю.
                                                  От того, что в описаниях ноутбуков будет найдено слово директор или кг — едва ли станет легче.

                                                  Нужна возможность настраивать результаты поиска, вручную говоря, что при запросе фамилии директора показывать на первом месте страничку с БИО, а не то, что «полнотекстовый поиск» посчитает более релевантным.

                                                  Посмотрите, как на HP.com поиск реализован — с историями поиска и подсказками — вы искали принтер, ноутбук, картридж?

                                                  Есть очень серьезный поисковый продукт atomz.com/ — там очень многие функции, недоступные бесплатным гугля-формам, реализованы.

                                                    +1
                                                    У меня нечто типа своей системы поиска с учетом морфологии и автообучением.
                                                    Методика проста.
                                                    Добавление в словарь:
                                                    1. Есть база с распарсеным словарём ханспел, по ней находится лексема («первая» словоформа ) добавляемого слова.
                                                    2. Если такого слова в ханспел-базе нет, спрашиваем у брата-яндекса все формы этого слова и добавляем в ханспел-базу (очень помогает при добавлении фамилий).
                                                    3. В итоге добавляем лексему (или просто слова если не нашли лексему) в поисковый индекс.

                                                    Поиск абсолютно также, у искомого слова ищем лексему, потом ищем её в индексе. Всё.

                                                    Есть еще одна ступень, но её сейчас редко применяю — исправление ошибок.
                                                    Пример — spravka.properm.ru/?search=%F6%FB%F0%EA
                                                    Вот здесь тот же поисковик, но без исправления ошибок — www.business-class.su/search.php?s=%EF%F0%EE%E2%E5%F0%EA%E0
                                                      0
                                                      Интересное решение! Могли бы Вы привести краткий пример, как это делается пошагово? Спасибо!
                                                      0
                                                      Я когда то написал свой поиск, долго им гордился :-), все через поискового робота который перерывал весь сайт заходя снаружи по всем ссылкам что находил и складывал все в базу с меткой где нашел.

                                                      Сейчас я понял что это глупости и для моих проектов хорошо использовать гугл, как это свободно делают многие хорошие сайты.
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                          0
                                                          Кстати в догонку к комментарию по использованию Zend Lucene.

                                                          Там есть возможность, которая не упомянута в документации — давать полям документа разный вес. Т.е. например если Вам надо, чтобы по слову Контакты находилась страница «Контакты», то надо добавить вес поле с заглавием страницы.

                                                          $titleField = Zend_Search_Lucene_Field::Unstored('title', strtolower($my_symfony_object->getTitle()));

                                                          $titleField->boost = 1.5;

                                                          $doc->addField($titleField);

                                                          вот отсюда:
                                                          www.nabble.com/Zend_Search_Lucene-field-boost--td9439937.html#a9441132
                                                            0
                                                            Уже есть silver bullet — sphinxsearch.com, дропайте свои велосипеды с лайками.
                                                              +1
                                                              Как инсайдер, обязан отметить quintura.ru. Ни в тексте, ни в коментах ее нет. Однако и с полнотой, и с точностью, и с ранжированием у нас все очень неплохо. И подогнать под дизайн сайта вполне умеем. И настроить выдачу на вашем сайте — настроим. И нужные страницы подложим. И весь инструментарий предоставим. Красота! + закладки «табы» для поиска в разных разделах одного сайта, или по разным сайтам одного издателя.
                                                                0
                                                                а под MSsql 2008, есть стороние решения?
                                                                мы пользовались до сих пор SQL turbo (Imceda) пока их не купил майкрософт, но так и не применил технологию.

                                                                есть решения?
                                                                  +1
                                                                  многие поисковики работают с реляционными БД. Чаще всего как минимум доступен интерфейс ODBC. Достоверно могу сказать про встроенную поддержку в Sphinx&Яндекс.Сервере
                                                                    0
                                                                    спс. посмотрим

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

                                                                Самое читаемое