Синонимы с использованием 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%... но в прошлом это отлично работало для меня.