понедельник, 30 апреля 2012 г.

Solr & Lucene


                                     Lucene Logo



Содержание
1.   Apache Solr & lucene
  • Что такое Lucene?
  • Что такое Solr?
  • История возникновения.
  • Текущее состояние. Последняя версия.
2.   Где используется
  • Кросплатформенность, примеры проектов(http://wiki.apache.org/solr/PublicServers)
  • Готовые клиенты для множества языков разработки (в том числе PHP)
3.   Возможности
  • Масштабирование - репликация и шардинг в составе платформы
  • Высокая скорость индексации
  • Индексация в реальном времени
  • Поддержка языков
  • Гибкость благодаря мощной системе конфигурации
  • RunTime конфигурация
  • Работа с различными форматами данных(pdf, doc, json, xml)
  • Индексирование баз данных
  • Кэширование
  • Фильтрация
  • Backup индекса
  • Web панель администрирования
  • Расширяемость благодаря поддержке плагинов
  • Текстовый анализ (разнообразные текстовые фильтры)
  • Язык запросов (фильтры, сортировки, работа с датой/временем, функциональные запросы и многое другое)
  • Приблизительный поиск (неточные совпадения) и проверка запросов на ошибки (подсказки вариантов)
4.   Работа с базами данных
  • Поддержка различных типов баз данных
  • Структура базы данных
  • Оптимизация работы с базой данных, нормализация.
5.   Конфигурация
  • Файлы конфигурации
  • Понятие Документ
  • Stemming, lemmatization - tokenization
  • Анализаторы
  • Schema.xml
  • Создание типов полей
  • Описание полей
  • SolrConfig.xml
  • Файлы конфигурации импорта
  • Описание сущностей документа
  • Парсер запросов Dismax
  • Конфигурация работы в режиме многоядерности
  • Настройка Фильтрации
  • Настройка сортировки
  • Использование расширенного парсера запросов Edismax
6.   Тестирование
  • ПП для измерения производительности: индексирование, поиск
  • Debug режим






Who is who
Apache Solr - это расширяемая поисковая платформа от Apache. Система основана на библиотеке Apache Lucene и разработана на Java. Особенности ее в том, что она представляет из себя не просто техническое решение для поиска а именно платформу, поведение которой можно легко расширять/менять/настраивать под любые нужды - от обычного полнотекстового поиска на сайте до распределенной системы хранения/получения/аналитики текстовых и других данных с мощным языком запросов.

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

solr history
В 2004, Solr был создан Yonik Seeley в CNET Networks как проект добавляющий возможность поиска на сайте компании. Yonik Seeley вместе с Grant Ingersoll и Erik Hatcher пошли на запуск Lucid Imagination, обеспечивая коммерческую поддержку, консультации и обучение для Apache Solr поисковых технологий.

В январе 2006, CNET Networks открыто опубликовали исходный код, жертвуя ее на Apache Software Foundation . Как любой новый проект в Apache Software Foundation Solr был введен в инкубационный период.

В январе 2007, у Solr закончился инкубационный период, к этому моменту у проекта было достаточно много особенностей для привлечения сообществ пользователей сотрудников и коммитеров. Так же к этому времени Solr уже использовался на некоторых сайтах с высоким трафиком.
lucene history
Lucene изначально был написан Doug Cutting в 1999. И первоначально был доступен для загрузки с SourceForge. Lucene присоединился к Apache Software Foundation's Jakarta family продуктам с открытым исходным кодом в сентябре 2001.
current versions

Текущая версия Solr - http://lucene.apache.org/solr/

Текущая версия Lucene - http://lucene.apache.org/core/

there ...
Solr кроссплатформенный программный продукт, по данной ссылке можно посмотреть некоторые сайты использующие Solr как поисковую систему.
Так же Lucene имеет порты на другие языки.
Lucene портирована (или сейчас портируется на другие языки программирования):
Why is that?

Начиная знакомство с великим и могучим SOLR советую прочитать вот этот пост. Возможно прочитанное там упасет вас от многих ошибок в дальнейшем...

Масштабирование - репликация и шардинг в составе платформы
Ну что сдесь скажешь? разделяй расширяй настраивай - solr со всем справится.

Высокая скорость индексации
Здесь я думаю стоит немного уточнить из личного небольшого опыта:
  • допустим у нас есть база данных и в ней таблица (или несколько) которые мы будем индексировать. Пусть записей в таблице 3 млн. И колонки с текстовыми данными которые нам так важны будут не больше 1000 символов. у меня индексация подобной базы заняла не больше часа. 
  • а теперь допустим, что у нас есть дамп базы данных страниц WIKIPEDIA. и пусть таблицы там содержат по 2.5 млн записей. Сам дамп вливается в базу достаточно долга , все таки 15 гигабайт. У меня размер колонок с текстовыми данными варьировался от 6 килобайт до нескольких мегабайт но в среднем это ~100kB. Так вот здесь уже, толи от того, что я с mysql работал, толи ещё от чего, но на локальной машине полное индексирование с оптимизацией у solr заняло 17 часов. Но ...
Индексация в реальном времени
Solr хорошо работает с дельта индексированием

Поддержка языков
По умолчанию стеммер Solr поддерживает такие языки:
Danish, Dutch, English, Finnish, French, German2, German,Italian
Kp, Lovins, Norwegian, Porter, Portuguese

Russian
Spanish, Swedish
Поэтому, как видите с русской морфологией все ОК. Освещено здесь :http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
Другой вариант - Вы можете взять за основу алгоритм snowball http://snowball.tartarus.org/algorithms/russian/stemmer.html и написать свой собственный стеммер.
Вот здесь реализован поиск на Solr: http://music.nur.kz/search по русским исполнителям.

RunTime конфигурацияОчень важная возможность на мой взгляд. Просто вбиваем:
localhost:8080/solr/dataimport?command=reload-config
и все файлы конфигурации перечитаны и применены. И не нужно перезапускать все и всех.

Работа с различными форматами данных(pdf, doc, json, xml)Здесь особо тоже сказать ничего не могу, но все, что может вызвать затруднения можно найти на http://wiki.apache.org/solr/
Индексирование баз данных
Базы данных индексируются не зависимо от типа (mysql, oracle, postgres). Вся сложность - добавили jar для работы с данным типом базы данных . написали конфигурацию запросов , запустили full-import и все.

КэшированиеВесьма полезная вещь если ей не злоупотреблять. В первый раз мы ищем, результат кэшируется, и в последствии до перезапуска сервиса результаты по данному запросу будут возвращаться за миллисекунду.
ФильтрацияВ Solr’e есть очень полезная штука – FilterQuery (fq). Она используется чтобы фильтровать результат выборки, уже после самой выборки, что очень полезно, так как сама выборка может быть закеширована Solr, а конечная выборка, после фильтрации – нет. Это означает что при использовании фильтра в таком же запросе, но с другими параметрами фильтрации можно использовать предыдущую выборку из кэша.

Backup индексанапример http://host:8080/solr/replication?command=backup&location=/home/jboss/backup ещё есть жесткие ссылки но это тоже в wiki

Web панель администрированияhttp://hostname:8983/solr/admin/


Расширяемость благодаря поддержке плагинов
Текстовый анализ (разнообразные текстовые фильтры)про анализаторы токенизаторы и тому подобном можно вот здесь немного полистать

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

Lucene не отстаёт от поискового гиганта и предоставляет свой, аналогичный язык запросов. Кроме указанных операторов Lucene поддерживает логические запросы с использованием AND и OR, символы замены (wildcards), нечёткий поиск (fuzzy search) и многое другое.

Приблизительный поиск (неточные совпадения) и проверка запросов на ошибки (подсказки вариантов)
с этим я думаю все понятно.

hello dolphin ORA and postgra...
как я уже упоминал Solr умеет работать с различными типами баз данных, и принципиальной разницы здесь нет. создается некоторый конфигурационный файл в котором указывается где эта база находится кто пользователь и какой у него пароль, а все остальное это язык SQL запросов к базе. 
На что стоило бы обратить внимание так это структура базы которую вы собираетесь индексировать. Все понимают что если запросы будут содержать много JOIN и таму подобного то такой нетривиальный процесс как индексирование может отнять много времени. Так что прежде чем подумать прикрутить к своему проекту полнотекстовой поиск подумайте о текущей структуре вашей базы данных. Нормализацию никто не отменял. 
для наглядности предоставлю несколько ссылок

Config config config

Файлы конфигурации
их не много. основные это schema.xml и solrconfig.xml. к дополнительным относятся те файлы которые вы создаете для конфигурации ваших импортеров данных (будь то импортеры для базы данных и все остальные). Schema.xml описывает типы данных которые будут использоваться при индексировании для различных сущностей, как с данными типами работать. так же schema содержит все сущности которые будут индексироваться и добавляться в документы. SolrConfig - это есть основная конфигурация для solr.

Понятие Документorg.apache.solr.common.SolrDocument
Конкретное представление документа в индекс Solr. В отличие от Lucene документов, SolrDocument может иметь значением объекта соответствующий тип, определенный в schema.xml для индексирования документов, использовать SolrInputDocument, который содержит дополнительную информацию для документа и поля повышения рейтинга.
Документ это некоторая единица хранения информации выбранной из базы данных или другого источника . легче рассмотреть на примере:

<add>
<doc>
 <field name="id">TWINX2048-3200PRO</field>
 <field name="manu">Corsair Microsystems Inc.</field>
 <field name="cat">electronics</field>
 <field name="cat">memory</field>
 <field name="payloads">electronics|6.0 memory|3.0</field>
</doc>

<doc>
 <field name="id">VS1GB400C3</field>
 <field name="manu">A-DATA Technology Inc.</field>
 <field name="cat">electronics</field>
 <field name="cat">memory</field>
 <field name="payloads">electronics|4.0 memory|2.0</field>
</doc>

<doc>
 <field name="id">VDBDB1A16</field>
 <field name="manu">A-DATA Technology Inc.</field>
 <field name="cat">electronics</field>
 <field name="cat">memory</field>
 <field name="payloads">electronics|0.9 memory|0.1</field>
</doc>

</add>

Что нам говорит этот файл? нужно добавить 3 документа с некоторыми полями. так вот документ и хранит проиндексированую информацию и именно по документам производится поиск в solr.

Stemming, lemmatization - tokenizationТекст разбивается на токены, то есть токенизируется (tokenizing). В простейшем случае разбиение происходит по пробелам и знакам препинания, однако это поведение может регулироваться. Во-вторых, каждый токен приводится к своей морфологической основе (stemming): обрезаются окончания, распространённые суффиксы заменяются на стандартную форму и т.д. Например, слово «questioning» из примера выше будет преобразовано в «question». В дальнейшем это позволит игнорировать при поиске форму слова, выдавая более точные результаты. Преобразование происходит на основе ряда простых логических правил и не всегда даёт правильный с точки зрения лингвистики результат, однако в большинстве случаев это не играет значительной роли. В-третьих, из списка токенов выбрасываются так называемые stop-words – наиболее распространённые, но не несущие особой смысловой нагрузки слова. Для английского языка это такие слова как “a", “the", “and" и т.д. В-четвёртых, каждому токену присваивается ряд атрибутов, часть из которых в дальнейшем попадает в индекс, а часть – используется на более поздних стадиях, но отбрасывается при сохранении в индекс. (На самом деле в последних версиях Lucene даже сам токен рассматривается просто как атрибут некоторого объекта.)
Анализаторы
стадии работы с текстом объединены в так называемых анализаторах. Выбор анализатора зависит от нескольких параметров, и в первую очередь от языка текста. Ветвь contrib из репозитория Lucene предоставляет довольно интересный анализатор –SnowballAnalyzer. В отличие от прочих анализаторов, SnowballAnalyzer не заточен ни на один конкретный язык, а принимает название языка в виде строки в своём конструкторе. В сочетании с автоматическим определителем языка из проекта Tika, он может оказаться прекрасным решением для многоязычных корпусов текстов.

Среди других анализаторов стоит выделить KeywordAnalyzer, который индексирует всё анализируемое поле как единый токен. Это может быть полезно для таких полей как номер телефона, ID, различные коды и т.д.
Schema.xmlОдним из конфигурационных файлов, которые описывают реализации Solr является schema.xml. Schema.xml описывает одну из самых важных  реализации - структуру данных индекса. Информация , содержащаяся в настоящем файлов позволяют вам контролировать, как Solr ведет себя при индексировании данных, либо при создании запросов. Schema.xml хранит не только саму структуру индекса, но ,также, подробную информацию о типах данных, которые имеют большое влияние на поведение Solr, к которым обычно относятся с пренебрежением.

Пример shema.xml
Создание типов полей
Объявление новых или изменение существующих типов полей это задача под конкретные цели.  Достаточно хорошее описание можно найти здесь.

Описание полей
Существует два вида объявления полей 
  • Статический 
  • динамический
Эти поля обрабатываются по-разному Solr. Статический тип поля имеет только одно название. Динамические поля - это поля доступные под многими именами. На самом деле имена динамических полей являются простым регулярным выражением (имя, начинающееся и заканчивающееся на '*' знак). Обратите внимание, что Solr сначала выбирает статические поля, а потом динамическое поля. Кроме того, если имя поля соответствует более чем одному определению, Solr выберет поле с более длинным названием pattern.
  • name - имя поля (обязательный атрибут).
  • type - тип поля, которое является одним из предопределенных типов (обязательный атрибут).
  • indexed  - должно ли поле индексироваться (установить true , если вы хотите найти или отсортировать по этому полю).
  • stored - сохранить исходные значения (установить true  , если мы хотим получить исходное значение поля).
  • omitNormshttp://www.lucidimagination.com/content/scaling-lucene-and-solr#d0e71 (значение истинной для поля, для которых Вы будете использовать полнотекстовый поиск).
  • termVectors - установлен истинный в случае, если мы хотим сохранить так называемый срок векторов. По умолчанию значение параметра ложной . Некоторые функции требуют установки этого параметра на истинный (например, MoreLikeThis или FastVectorHighlighting ).
  • termPositions - установлен истинный , если вы хотите сохранить позиции term с term вектора.Установка для истинных приведет индекс к расширению его размер.
  • termOffsets - установлен истинный , если вы хотите сохранить term смещения вместе с term вектора. Установка для истинных приведет индекс к расширению его размер.
  • default - задает значение по умолчанию, если документ не получил никакого значения в этой поле.
SolrConfig.xml
основной файл конфигурации. В нем описаны
  • обработчики запросов
  • Listeners (процессы, которые "слушают" для конкретного запроса события, связанные, слушатели могут быть использованы для запуска выполнения специального кода, такие как применение некоторых общих запросов для разогрева кэша)
  • Запрос диспетчера для управления HTTP-связями
  • Администрирование веб-интерфейса
  • параметры, связанные с репликацией и дублирование (эти параметры подробно описаны в Масштабирование и распределение )
Файлы конфигурации импорта
вот пример конфигурации для импорта из базы данных wikipedia. Многословность здесь излишне:
<dataConfig>
<dataSource
type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/wiki"
user="root"
password="password"
batchSize="-1"
/>
<document>
<entity
name="pages"
query="SELECT p.page_id as pid,
             p.page_namespace as pns,
             CONVERT(p.page_title USING utf8) as pt
            FROM page as p
      ">
<field column="pid" name="id" />
<field column="pns" name="field_namespace_id" />
<field column="pt"  name="field_title" />

<!-- Store the full text of the article -->
<entity
name="fulltext"
query="SELECT CONVERT(t.old_text USING utf8) as ft
      FROM text t
      LEFT JOIN (revision as r) ON (t.old_id = r.rev_text_id )
      LEFT JOIN (page as p) ON ( r.rev_id= p.page_latest)
      WHERE p.page_id='${pages.pid}'">
<field column="ft" name="field_full_text" />
</entity>
</entity>
</document>
</dataConfig>


Описание сущностей документа
Entity имеет несколько очень важных свойств.
name (обязательно): уникальное имя используется для идентификации лица
processor : Требуется только, если источник данных не СУБД. (Значение по умолчанию SqlEntityProcessor )
transformer : Трансформаторы для применения к этой сущности. (
dataSource Тип : имя источника данных (используется, если есть несколько источников данных).
threads : поток используемый для запуска этой сущности.
Внимание: Не все комбинации компонентов DIH можно безопасно использовать с "threads". При использовании этой функции, не забудьте тщательно проверить!
Значительные ошибки, связанные с "threads" исправлены в Solr3.6 . При использовании этой функции с более старой версией, рекомендуется обновление .
Параметр "threads" устарел в Solr3.6 и планируется к удалению в Solr4.0 .
рк : первичный ключ для сущности. Это дополнительный параметр и только необходим при использовании дельта-импорта. Ключ не имеет никакого отношения к uniqueKey определенного в schema.xml но они оба могут быть одинаковыми.
rootEntity : По умолчанию сущность, являются основными субъектами документа. Если она установлена ​​в false, сущность подпадающие под это объявление будет рассматриваться как корневой объект .
OnError : (прервать | пропуск| дальше). Значение по умолчанию "прервать". "Пропустить" пропустить текущий документ. "Продолжить" продолжается, как если бы ошибки не произошло. Solr1.4
preImportDeleteQuery : до полного импорта этого будет использоваться для очистки индекса вместо '*: *.
postImportDeleteQuery : после полного импорта этого будет использоваться для очистки индекса <!>.
Для SqlEntityProcessor атрибуты сущности:
query (обязательно): SQL запрос в БД
deltaQuery : Используется в дельта-импорте
parentDeltaQuery : Используется в дельта-импорте
deletedPkQuery : Используется в дельта-импорте
deltaImportQuery : (используется только в дельта-импорте). Если значение не установлено, DIH пытается сделать запрос импорта.
Парсер запросов Dismaxhttp://wiki.apache.org/solr/DisMax

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

Настройка ФильтрацииФильтры запросов применяются для выбора результатов после того, как вернулись результаты  поиска. Огромная тема http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters

Настройка сортировкиСортировка может быть сделано по "score" документа, или на любом multiValued="false" indexed="true" поля при условии, что поле либо не токинезировано (т.е. не имеет Analyzer) или использует анализатор, который производит только один term (т.е. использует KeywordTokenizer)

Вы можете сортировать по индексу ID с помощью sort = _docid_ по возрастанию или sort=_docid_ desc

По состоянию на Solr3.1 , сортировка может быть сделано по произвольным запросам функции (как в FunctionQuery ).

Использование расширенного парсера запросов Edismax
http://wiki.apache.org/solr/ExtendedDisMax?highlight=%28edismax%29


TESTS ....

ПП для измерения производительности: индексирование, поискЧто такое SolrMeter?
Основная цель этого проекта с открытым кодом, это дать сообществу пользователей Solr "универсальный инструмент для взаимодействия именно с Solr", написав запросы и добавив документы, можно убедиться, что ваша реализация Solr готова к реальному использования. С SolrMeter вы можете моделировать вашу рабочую нагрузку по индексу Solr и получать статистику в графическом виде.

Debug режимhttp://localhost:8983/solr/admin/analysis.jsp
You can start the example application in debug mode to debug your java class with your favorite IDE (like eclipse).
java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -jar start.jar
Then connect to port 8000 and debug.


epilog

http://notes.sochi.org.ru/3088/

https://docs.google.com/drawings/edit?id=1DvoSWb8dIrRM-JP3FlUU5QGcg93SJH5tmh4vx1_d6d0&hl=en&authkey=CNiDqc4BКак работают поисковые системы на базе Lucene
http://dev.by/blog/27079

http://notes.sochi.org.ru/3088/ семь смертных грехов solr