Синонимы с использованием Lucene

Каков наилучший способ обработки синонимов (фраз) с помощью Lucene? Особенно, когда мне нужно выполнить такие запросы, как: a ИЛИ b ИЛИ c NOT d

Как добавить новое поле под названием "синонимы" для каждого документа при индексировании? Это значение поля будет иметь список всех синонимов. Он будет добавлен в документ только тогда, когда в этом документе есть какой-либо синонимы.

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

Может ли этот подход хорошо работать для любого запроса?

FYI, Синонимы в моем приложении полностью настраиваются, а не из английского словаря... т.е. "Глобальный лидер в области финансов" также может означать "Лучший инвестиционный банк" или "Финансовая компания Fortune 500" и т.д. И т.д.

Просьба предложить.

Спасибо.

Ответы

Ответ 1

Есть вклад в проект Lucene под названием "wordnet". Согласно его документации:

В этом пакете используются синонимы, определенные WordNet, для создания индекса Lucene, который их хранит, что, в свою очередь, может использоваться для расширения запроса. Обычно вы запускаете Syns2Index для создания индекса запроса/ "базы данных", а затем вызываете SynExpand.expand(...) для расширения запроса.

Он включает в себя образец того, что он делает:

Если вы передадите запрос "большая собака", он распечатает:

Запрос: big adult^0.9 bad^0.9 bighearted^0.9 boastful^0.9 boastfully^0.9 bounteous^0.9 bountiful^0.9 braggy^0.9 crowing^0.9 freehanded^0.9 giving^0.9 grown^0.9 grownup^0.9 handsome^0.9 large^0.9 liberal^0.9 magnanimous^0.9 momentous^0.9 openhanded^0.9 prominent^0.9 swelled^0.9 vainglorious^0.9 vauntingly^0.9 dog andiron^0.9 blackguard^0.9 bounder^0.9 cad^0.9 chase^0.9 click^0.9 detent^0.9 dogtooth^0.9 firedog^0.9 frank^0.9 frankfurter^0.9 frump^0.9 heel^0.9 hotdog^0.9 hound^0.9 pawl^0.9 tag^0.9 tail^0.9 track^0.9 trail^0.9 weenie^0.9 wiener^0.9 wienerwurst^0.9

Вы видите, что исходные слова ( "большой" и "собака" ) не имеют привязки к ним. Синонимы, однако, имеют взвешивание (0,9), которое вы можете настроить самостоятельно.

Он поставляется в комплекте со стандартным распределением Lucene в каталоге "contrib".

Ответ 2

Вы можете получить объект Query после разбора строки запроса ввода с помощью QueryParser.parse().

В большинстве случаев запрос верхнего уровня представляет собой логический запрос с подзапросами в качестве его дочерних элементов. Вы можете рекурсивно перебирать объект запроса. Когда вы нажмете объект TermQuery или PhraseQuery, вы можете получить запрос (sub) и заменить этот объект запроса логическим объектом запроса, состоящим из его синоимов, если таковые имеются.

По существу, вы преобразовываете исходный запрос

a OR b AND c 

to

(a OR synA) OR (b OR synB1 OR synB2) AND c

Работа в объекте запроса гарантирует, что вы просто заменяете листовые узлы запроса новыми запросами и не играете с произвольно сложной иерархией запросов.

Ответ 3

Я предпочитаю запускать поиск, используя всю введенную фразу, и весит все, что было тяжелее, чем следующая серия поисков. Затем мне нравится повторять каждое слово во фразе и искать с этим результатом, получая более низкий балл. Затем я объединяю баллы для всех предметов, возвращаемых более одного раза, и сортировать результаты соответственно. Это может быть не самый лучший способ сделать это на 100%... но в прошлом это отлично работало для меня.