Pull to refresh

Полнотекстовый поиск в веб-проектах: Sphinx, Apache Lucene, Xapian

Reading time 15 min
Views 55K
Полная авторская верcия из моего блога. Оригинал материала написан специально для Developers.org.ua

Наверное любой современный веб-проект сложно себе представить без… без контента! Да, именно контент в разных его проявлениях сегодня «правит бал» в различных веб-проектах. Не так важно — создаваемый пользователями или получаемый из других источников автоматически — информация является основной любого (ну, или почти любого) проекта. А раз так — то вопрос поиска необходимой информации стоит очень остро. И острее с каждым днем, ввиду стремительного расширения количества этого самого контента, в основном за счёт создаваемого пользователями (это и форумы, и блоги и модные нынче сообщества, вроде Habrahabr.ru). Таким образом, любой разработчик, реализующий сегодня какой-либо проект, сталкивается с потребностью реализовать поиск в своём веб-приложении. При этом требования к такому поиску уже намного сложнее и шире, чем даже год-два назад. Конечно, для каких-то проектов вполне подойдёт и простое решение, к примеру, вполне можно использовать Custom Google Search. Но чем более сложное приложение, и чем сложнее структура контента, если требуются особые виды поиска и обработки результата, или же просто количество или формат данных в вашем проекте особый, вам потребуется собственная поисковая система. Именно своя система, собственный поисковый сервер или сервис, а не сторонний, пусть даже гибкий и настраиваемый. Но что же выбрать, и вообще — какие сейчас на рынке есть поисковые проекты, которые готовы для использования в реальных проектах, не исследовательских или научных, а реальных бизнес-приложениях? Далее мы кратко рассмотрим различные варианты поисковых решений, пригодных для встраивания в ваше веб-приложение или развёртывания на собственном сервере.

Общая архитектура и термины

И так, для более глубокого понимания сути поиска мы попробуем кратко ознакомится с используемыми понятиями и терминами. Под поисковым сервером (или просто «поисковик») мы понимаем библиотеку или компонент, вообще, программное решение, которое самостоятельно ведёт свою базу данных (на самом деле это может быть и СУБД, и просто файлы и распределённая платформа хранения) документов, в которых, собственно, и происходит поиск, предоставляет сторонним приложениям добавлять, удалять и обновлять документы в этой базе. Этот процесс называется индексированием, и может быть реализовано отдельным компонентом или сервером (индексатором). Другой компонент, именно поисковый механизм, принимает запрос на поиск и обрабатывая созданную индексатором базу производит выборку данных, которые соответствуют запросу. Кроме этого, он может вычислять дополнительные параметры для результатов поиска (ранжировать документы, вычислять степень соответствия поисковому запросу и т.п.). Это самые важные системы поисковика, и они могут быть как монолитно реализованы в одной библиотеке, так и быть самостоятельными серверами, доступ к которым реализуется через различные прикладные протоколы и API. Дополнительно, в поисковом сервере может быть реализована предварительная обработка документов перед индексацией (например, извлечение текста с файлов различных форматов или баз данных), различные API также могут реализоваться дополнительными компонентами. Сам сервер может хранить свои индексные данные в базе данных (как встроенной, так и используя внешний сервер, например, MySQL), в виде файлов собственного оптимизированного формата или даже использовать специальную распределённую файловую систему.

Отдельно я бы выделил наличие модуля реализации веб-поиска. То есть, в поисковом сервере может быть реализована встроенная возможность получать документы с веб-сайтов по протоколу НТТР и заносить их в индекс. Этот модуль называется обычно «паук» или «crawler», и таким образом, поисковый сервер уже может быть похож на «настоящий» и привычный всем поиск вроде Google или Yandex. Так можно реализовать собственный поисковик по нужным вам сайтам, например, посвящённым одной теме — достаточно просто создать список адресов и настроить их периодических обход. Однако это уже задача гораздо более сложная и серьёзная, как технически, так и организационно, поэтому мы не останавливаемся на деталях её реализации. Среди проектов, которые мы рассмотрим, присутствует один сервер, именно реализующий веб-поисковик, то есть содержит все необходимое для создания «убийцы Яндекса». Интересно?

Какие параметры важны?

При выборе поискового механизма следует учитывать следующие параметры:
  • скорость индексирования — то есть, как быстро поисковый сервер «перемалывает» документы и заносит их в свой индекс, делая доступным поиск по ним. Обычно измеряется в мегабайтах чистого текста в секунду.
  • скорость переиндексации — в процессе работы документы изменяются или добавляются новые, поэтому приходится переиндексировать информацию. Если сервер поддерживает инкрементное индексирование, то мы обрабатываем только новые документы, а обновление всего индекса оставляем на потом или даже вообще не делать. Другие сервера требуют полной перестройки индекса при добавлении новой информации, либо используют дополнительные индексы (дельта-индекс), в который включается только новая информация
  • поддерживаемые API — если вы используете поисковик в связке с веб-приложением, обратите внимание на наличие встроенного API к вашему языку или платформе. Большинство поисковиков имеют API для всех популярных платформ — Java, PHP, Ruby, Phyton
  • поддерживаемые протоколы — кроме API важны и протоколы доступа, в частности, если вы захотите получить доступ с другого сервера или приложения, к которому нет родного API. Обычно поддерживаются XML-RPC (или разновидности, вроде JSON-RPC), SOAP или доступ через http/socket.
  • размер базы и скорость поиска — эти параметры очень взаимосвязаны и если вы реализуете что-то уникальное и предусматриваете, что у вас могут быть миллионы и больше документов в базе, по которым нужно производить мгновенный поиск, то посмотрите на известные реализации выбранной платформы. Хотя никто не заявляет явно про ограничения на количество документов в базах, и на небольших коллекциях (например, несколько тысяч или десятков тысяч документов) все поисковики будут примерно одинаковые, но если речь идёт о миллионах документов — это может стать проблемой. Кстати говоря, сам по себе этот параметр не всегда имеет значение, нужно смотреть на особенности каждой системы и алгоритмы работы с поиском, а также на другие параметры, например, скорость переиндексации или возможные типы индексов и системы их хранения.
  • поддерживаемые типы документов — конечно, любой сервер поддерживает обычный текст (хотя следует смотреть на возможность работы с многоязычными документами и кодировкой UTF-8), но если вам необходимо индексировать разные типы файлов, например, HTML, XML, DOC или PDF, то стоит посмотреть на те решения, где есть встроенный компонент для индексации различных форматов и извлечения из них текста. Конечно, все это можно сделать прямо в вашем приложении, но лучше поиска готовые решения. Сюда же относится и поддержка индексирования и поиска информации, которая хранится в СУБД — не секрет, что такое хранение самое распространённое для веб-приложений, и лучше, чтобы поисковый сервер работал напрямую с базой данных, без необходимости вручную извлекать и «скармливать» ему документы для индексирования.
  • работа с разными языками и стемминг — для корректного поиска с использованием разных языков необходима родная поддержка не только кодировок, но и работа с особенностями языка. Все поддерживают английский язык, который для поиска и обработки достаточно простой, но для русского и других аналогичных необходимо использовать автоматические средства для обеспечения морфологии. Модуль стемминга позволяет склонять и разбирать слова в поисковом запросе для более корректного поиска. Если для вас критичен поиск на русском языке, обратите внимание на присутствие этого модуля и его особенности (конечно, ручной стемминг лучше автоматического, но сложнее, хотя и автоматические есть очень разные).
  • поддержка дополнительных типов полей в документах — кроме самого текста, который индексируется и в котором производится поиск, необходимо наличие возможности хранить в документе неограниченное количество других полей, которые могут хранить мета-информацию о документе, что необходимо для дальнейшей работы с результатами поиска. Очень желательно, чтобы количество и типы полей не ограничивались, а индексируемость полей можно было настраивать. Например: в одном поле хранится название, во втором — аннотация, в третьем — ключевые слова, в четвёртом — идентификатор документа в вашей системе. Необходимо гибко настраивать область поиска (в каждом поле или в указанных), а также те поля, которые будут извлекаться с базы поисковика и выдаваться в результатах поиска.
  • платформа и язык — это так же важно, хотя и в меньшей степени. Если вы собираетесь выделять поиск в отдельный от приложения модуль или сервер, или даже выносите его на отдельный сервер (железо в смысле), то роль платформы не такая и большая. Обычно это или C++ или Java, хотя есть варианты и для других языков (обычно порты решений на java).
  • наличие встроенных механизмов ранжирования и сортировки — особенно хорошо, если поисковик можно расширять (и он написан на известном вам языке) и написать нужные вам реализации этих функций, ведь существует очень много разных алгоритмов, и не факт, что используемый по умолчанию в поисковике вам подойдёт.

Конечно, есть ещё очень много разных параметров, да и сама область поиска данных достаточно сложная и серьёзная, но для наших применений этого вполне достаточно. Вы же не делаете конкурента Google?

Теперь кратко расскажем о тех поисковых решениях, на которые вам следует обратить внимание, только вы решите приступить к вопросу о поиске. Я намеренно не рассматриваю встроенные в вашу СУБД решение — FULLTEXT в MySQL и FTS в PostgreSQL (интегрирован в базу с версии, если не ошибаюсь, 8.3). В MySQL решение не может применяться для серьёзного поиска, особенно по большим объёмам данных, поиск в PostgreSQL намного лучше, но только если вы уже применяете эту базу. Хотя, как вариант — ставить отдельный сервер БД и там использовать только хранение данных и поиск тоже вариант. К сожалению, не имею на руках данных о реальных применениях на больших объёмах данных и сложных запросах (единицы и десятки Гб текста).


Sphinx search engine
  • Тип: отдельный сервер, MySQL storage engine
  • Платформа: С++/кросс-платформенный
  • Индекс: монолитный + дельта-индекс, возможность распределённого поиска
  • Поисковые возможности: булевый поиск, поиск по фразам и т.п. с возможностью группировки, ранжирования и сортировки результата
  • API и протоколы: SQL DB (а также встроенная поддержка MySQL и PostgreSQL), собственный XML-интерфейс, встроенные API для РНР, Ruby, Python, Java, Perl
  • Поддержка языков: встроенный английский и русский стемминг, soundex для реализации морфологии
  • Дополнительные поля: да, неограниченное количество
  • Типы документов: только текст или собственные XML-формат
  • Размер индекса и скорость поиска: очень быстрый, индексация около 10 Мб/сек (зависит от CPU), поиск около 0.1 сек/~2 — 4 Гб индексе, поддерживает размеры индекса в сотни Гб и сотни миллионов документов (это если не использовать кластеризацию), однако есть примеры работ на терабайтных базах данных.
  • Лицензия: open source, GPL 2 или коммерческая.
  • URL: http://sphinxsearch.com

Sphinx вероятно самый мощный и быстрый из всех открытых движков, которые мы рассмотрим. Особенно удобен тем, что имеет прямую интеграцию с популярными базами данных и поддерживает развитые возможности поиска, включая ранжирование и стемминг для русского и английского языка. Похоже, что отличную поддержку русского языка проект проект имеет из-за того, что автор — наш соотечественник, Андрей Аксенов. Поддерживаются и нетривиальные возможности вроде распределённого поиска и кластеризации, однако фирменной фичей является очень и очень высокая скорость индексации и поиска, а также способность отлично распараллеливаться и утилизировать ресурсы современных серверов. Известны очень серьёзные инсталляции, содержащие терабайты данных, поэтому Sphinx вполне можно рекомендовать как выделенный поисковый сервер для проектов любого уровня сложности и объёма данных. Прозрачная работа с самыми популярными базами данных MySQL и PostgreSQL позволяет его использовать в обычном для веб-разработки окружении, к тому же сразу «из коробки» есть API для разных языков, в первую очередь, для РНР без применения дополнительных модулей и библиотек расширения. Но сам поисковик необходимо компилировать и устанавливать отдельно, поэтому на обычном хостинге он неприменим — только VDS или собственный сервер, причём, желательно побольше памяти. Индекс у поисковика монолитный, поэтому придётся немного «извратиться», настраивая дельта-индекс для корректной работы в случае, когда очень много новых или изменённых документов, хотя огромная скорость индексации позволяет организовать перестройку индекса по расписанию и это не скажется на работе собственно поиска.

SphinxSE — это версия, функционирующая как движок хранения данных для MySQL (требует патча и перекомпиляции базы), Ultrasphinx — это конфигуратор и клиент для Ruby (кроме присутствующего в дистрибутиве API), кроме этого есть плагины для многих известных CMS b блог-платформ, вики, которые заменяют стандартный поиск (полный список смотрите здесь: http://www.sphinxsearch.com/contribs.html)


Семейство Apache Lucene
  • Тип: отдельный сервер или сервлет, встраиваемая библиотека
  • Платформа: Java/кросс-платформенный (есть порты на множество языков и платформ)
  • Индекс: инкрементный индекс, но требующий операции слияния сегментов (можно параллельно с поиском)
  • Поисковые возможности: булевый поиск, поиск по фразам, нечёткий поиск и т.п. с возможностью группировки, ранжирования и сортировки результата
  • API и протоколы: Java API
  • Поддержка языков: отсутствует морфология, есть стемминг (Snowball) и анализаторы для ряда языков (включая русский)
  • Дополнительные поля: да, неограниченное количество
  • Типы документов: текст, возможно индексация базы данных через JDBC
  • Размер индекса и скорость поиска: около 20 Мб/минута, размер индексных файлов ограничен 2 Гб (на 32-bit ОС). Есть возможности параллельного поиска по нескольким индексам и кластеризация (требует сторонних платформ)
  • Лицензия: open source, Apache License 2.0
  • URL: http://lucene.apache.org/

Lucene — самый известный из поисковых движков, изначально ориентированный именно на встраивание в другие программы. В частности, его широко используют в Eclipse (поиск по документации) и даже в IBM (продукты из серии OmniFind). В плюсах проекта — развитые возможности поиска, хорошая система построения и хранения индекса, который может одновременно пополнятся, удалятся документы и проводится оптимизация вместе с поиском, а также параллельный поиск по множеству индексов с объединением результатов. Сам индекс построен из сегментов, однако для улучшения скорости рекомендуется его оптимизировать, что часто означает почти те же затраты, что и на переиндексацию. Изначально присутствуют варианты анализаторов для разных языков, включая русский с поддержкой стемминга (приведения слов к нормальной форме). Однако минусом является все же низкая скорость индексации (особенно в сравнении с Sphinx), сложность работы с базами данных и отсутствие API (кроме родного Java). И хотя для достижения серьёзных показателей Lucene может кластеризироваться и хранить индексы в распределённой файловой системе или базе данных, для этого требуется сторонние решения, так же как и для всех остальных функций — например, изначально он умеет индексировать только обычный текст. Но именно в плане использования в составе сторонних продуктов Lucene «впереди планеты всей» — ни для какого другого движка нет столько портов на другие языки и использования. Одним из факторов такой популярности является и очень удачный формат файлов индексов, который используют сторонние решения, поэтому вполне можно строить решения, работающие с индексом и производящие поиск, но не имеющие собственного индексатора (это легче реализовать и требования намного ниже).

Solr — лучшее решение на базе Lucene, значительно расширяющее её возможности. Это самостоятельный сервер корпоративного уровня, предоставляющий широкие поисковые возможности в качестве веб-сервиса. Стандартно Solr принимает документы по протоколу HTTP в формате XML и возвращает результат также через HTTP (XML, JSON или другой формат). Полностью поддерживается кластеризация и репликация на несколько серверов, расширена поддержка дополнительных полей в документах (в отличие от Lucene, для них поддерживаются различные стандартные типы данных, что приближает индекс к базам данных), поддержка фасетного поиска и фильтрации, развитые средства конфигурирования и администрирования, а также возможности бекапа индекса в процессе работы. Встроенное кеширование также повышает скорость работы. С одной стороны, это самостоятельное решение на базе Lucene, с другой — её возможности очень существенно расширены относительно базовых, поэтому если вам необходим отдельный поисковый сервер, обратите сперва внимание на Solr.

Nutch — второй известнейший проект на базе Lucene. Это веб-поисковый движок (поисковый механизм + веб-паук для обхода сайтов) совмещённый с распределённой системой хранения данных Hadoop. Nutch «с коробки» может работать с удалёнными узлами в сети, индексирует не только HTML, но и MS Word, PDF, RSS, PowerPoint и даже MP3 файлы (мета-теги, конечно), по сути — это полноценный поисковик-убийца Google. Шучу, расплата за это — значительное урезание функционала, даже базового из Lucene, например не поддерживаются булевы операторы в поиске, не используется стемминг. Если стоит задача сделать небольшой локальный поисковик по местным ресурсам или заранее ограниченному набору сайтов, при этом нужен полный контроль над всеми аспектами поиска, или вы создаёте исследовательский проект для проверки новых алгоритмов, в таком случае Nutch станет вашим лучшим выбором. Однако учтите его требования к аппаратной части и широком канале — для реального web-поисковика счёт трафика идёт на террабайты.

Вы думаете, никто Nutch не использует «по-взрослому»? Ошибаетесь — из самых известных проектов, о которых вы могли слышать, его использует поисковая система по исходным кодам Krugle (http://krugle.com/).

Но не только за счёт проектов-надстроек известен и популярен Lucene. Будучи лидером среди открытых решений и воплотив в себя множество отличных решений, Lucene первый кандидат для портирования на другие платформы и языки. Сейчас имеются следующие порты (я имею ввиду те, что более-менее активно развиваются и максимально полные порты):
  • Lucene.Net — полный порт Lucene, полностью алгоритмически, по классах и API идентичный перенос на платформу MS.NET/Mono и язык C#. Пока проект находится в инкубаторе, а последний релиз датирован апрелем 2007 года (порт финальной 2.0 версии). Страница проекта.
  • Ferretпорт на язык Ruby
  • CLucene — версия на языке С++, что обещает дать существенный прирост производительности. По некоторым тестам, он быстрее оригинала в 3 — 5 раз, а иногда и более (на индексации, поиск сравним или быстрее на всего 5 — 10%). Оказалось, что эту версию использует большое количество проектов и компаний — ht://Dig, Flock, Kat (поисковик для KDE), BitWeaver CMS и даже такие компании, как Adobe (поиск по документации) и Nero. Страница проекта
  • Pluceneреализация на Perl
  • PyLuceneреализация для Python-приложений, однако не полная и требует частично Java
  • Zend_Search_Lucene — единственный порт на язык РНР, доступный в составе Zend Framework. Кстати, он вполне работоспособен и как самостоятельное решение, вне фреймворка, я проделал эксперименты и в результате выделения весь поисковый механизм теперь занимает всего 520 Кб в одном-единственном РНР файле. Домашняя страница проекта: http://framework.zend.com/manual/en/zend.search.lucene.htm

Xapian
  • Тип: встраиваемая библиотека
  • Платформа: C++
  • Индекс: инкрементный индекс, прозрачно обновляемый параллельно с поиском, работа с несколькими индексами, in-memory индексы для небольших баз.
  • Поисковые возможности: булевый поиск, поиск по фразам, поиск с ранжированием, поиск по маске, поиск по синонимам и т.п. с возможностью группировки, ранжирования и сортировки результата
  • API и протоколы: С++, Perl API, Java JINI, Python, PHP, TCL, C# и Ruby, CGI интерфейс с XML/CSV форматом
  • Поддержка языков: отсутствует морфология, есть стемминг для ряда языков (включая русский), реализована проверка правописания в поисковых запросах
  • Дополнительные поля: отсутствует
  • Типы документов: текст, HTML, PHP, PDF, PostScript, OpenOffice/StarOffice, OpenDocument, Microsoft Word/Excel/Powerpoint/Works, Word Perfect, AbiWord, RTF, DVI, индексация SQL баз через Perl DBI
  • Размер индекса и скорость поиска: известны работающие инсталляции на 1.5 Тб индекса и количество документов в сотни миллионов.
  • Лицензия: open source, GPL
  • URL: http://xapian.org

Пока это единственный претендент на конкуренцию с господством Lucene и Sphinx, выгодно отличается от них наличием «живого» индекса, не требующего перестройки при добавлении документов, очень мощным языком запросов, включая встроенный стемминг и даже проверку орфографии, а также поддержку синонимов. Эта библиотека будет лучшим выбором, если у вас система на perl или же вам требуется развитые возможности остроения поисковых запросов и у вас происходит очень частое обновление индекса, при этом новые документы должны быть сразу доступны для поиска. Однако я не нашёл никакой информации о возможности добавлять к документам произвольные дополнительные поля и получать их с результатами поиска, поэтому связь системы поиска с вашей собственной может представлять определённые трудности. В пакет входит Omega — надстройка над библиотекой, которая готова для использования в качестве самостоятельного поисковика и как раз она отвечает за возможности индексации разных типов документов и CGI интерфейс.

Наверное, на этом наш обзор можно завершить. Хотя существует ещё множество поисковых механизмов, на проверку часть из них является портами или надстройками над уже рассмотренными. Например, промышленного уровня поисковый сервер для собственной CMS компании eZ, ezFind на самом деле не отдельный поисковик, а интерфейс к стандартному Lucene Java и включает его в свою поставку. Это же касается и компонента Search из их пакета eZ Components — он предоставляет унифицированный интерфейс для доступа к внешним поисковым серверам, в частности взаимодействует с Lucene сервером. И даже такое интересное и мощное решение, как Carrot и SearchBox — это серьёзно модифицированные версии той же Lucene, значительно расширенные и дополненные новыми возможностями. Самостоятельных же поисковых решений, с открытым кодом, которые полностью реализуют индексацию и поиск по собственных алгоритмах на рынке не так и много. А какое решение выбрать — зависит от вас и особенностей, часто совсем не очевидных, вашего проекта.

Выводы

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

Sphinx подойдёт вам, если необходимо индексировать большие объёмы данных в базе MySQL и вам важна скорость индексации и поиска, однако не требуются специфические возможности поиска вроде “fuzzy search” и вы согласны выделить на это отдельный сервер или даже кластер.

Если необходимо встроить поисковый модуль в ваше приложение, то лучше всего поиска готовые порты для вашего языка к библиотеке Lucene — для всех распространённых языков они есть, однако могут реализовывать далеко не все возможности оригинала. Если же вы разрабатываете приложение на Java, то Lucene однозначно лучший выбор. Однако учтите достаточную медленную индексации и необходимость частой оптимизации индекса (и требовательность к CPU и скорости диска). Для РНР это, по всей видимости, единственный приемлемый вариант полной реализации поиска без дополнительных модулей и расширений.

Xapian достаточно хороший и качественный продукт, однако менее распространённый и гибкий, чем остальные. Для приложений на С++ и требованиями к широким возможностям языка запроса он будет лучшим выбором, однако требует ручной доводки и модификаций для встраивания в собственный код или использования как отдельного поискового сервера.

Ссылки по теме
Tags:
Hubs:
+3
Comments 62
Comments Comments 62

Articles